/* * 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.ui; import com.codename1.components.OnOffSwitch; import com.codename1.components.SpanButton; import com.codename1.components.SpanLabel; import com.codename1.io.Util; import com.codename1.ui.animations.CommonTransitions; import com.codename1.ui.animations.ComponentAnimation; import com.codename1.ui.animations.Transition; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; import com.codename1.ui.events.DataChangedListener; import com.codename1.ui.events.FocusListener; import com.codename1.ui.events.ScrollListener; import com.codename1.ui.events.StyleListener; import com.codename1.ui.geom.Dimension; import com.codename1.ui.geom.Rectangle; import com.codename1.ui.layouts.Layout; import com.codename1.ui.plaf.Border; import com.codename1.ui.plaf.Style; import com.codename1.util.SuccessCallback; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A tool to facilitate selection and manipulation of UI components as sets. This uses fluent API style, similar * to jQuery to make it easy to find UI components and modify them as groups. * * <h3>Set Selection</h3> * * <p>Sets of components can either be created by explicitly adding components to the set, or by * providing a "selector" string that specifies how the set should be formed. Some examples:</p> * * <ul> * <li>{@code $("Label") } - The set of all components on the current form with UIID="Label"</li> * <li>{@code $("#AddressField") } - The set of components with name="AddressField"</li> * <li>{@code $("TextField#AddressField") } - The set of components with UIID=TextField and Name=AddressField</li> * <li>{@code $("Label, Button")} - Set of components in current form with UIID="Label" or UIID="Button"</li> * <li>{@code $("Label", myContainer)} - Set of labels within the container {@code myContainer}</li> * <li>{@code $("MyContainer *") } - All descendants of the container with UIID="MyContainer". Will not include "MyContainer".</li> * <li>{@code $("MyContainer > *") } - All children of of the container with UIID="MyContainer".</li> * <li>{@code $("MyContainer > Label) } - All children with UIID=Label of container with UIID=MyContainer</li> * <li>{@code $("Label").getParent() } - All parent components of labels in the current form.</li> * </ul> * * <h4>Tags</h4> * * <p>To make selection more flexible, you can "tag" components so that they can be easily targeted by a selector. * You can add tags to components using {@link #addTags(java.lang.String...) }, and remove them using {@link #removeTags(java.lang.String...) }. * Once you have tagged a component, it can be targeted quite easily using a selector. Tags are specified in a selector with a {@literal .} * prefix. E.g.:</p> * * <ul> * <li>{@code $(".my-tag") } - The set of all components with tag "my-tag".</li> * <li>{@code $("Label.my-tag") } - The set of all components with tag "my-tag" and UIID="Label"</li> * <li>{@code $("Label.my-tag.myother-tag")} - The set of all components with tags "my-tag" and "myother-tag" and UIID="Label". Matches only components that include all of those tags.</li> * </ul> * * <h3>Modifying Components in Set</h3> * * <p>While component selection alone in the ComponentSelector is quite powerful, the true power comes when * you start to operate on the entire set of components using the Fluent API of ComponentSelector. ComponentSelector * includes wrapper methods for most of the mutator methods of {@link Component}, {@link Container}, and a few other common * component types.</p> * * <p>For example, the following two snippets are equivalent:</p> * * <pre> * {@code * for (Component c : $("Label")) { * c.getStyle().setFgColor(0xff0000); * } * } * </pre> * * and * * <pre> * {@code * $("Label").setFgColor(0xff0000); * } * </pre> * * <p>The second snippet is clearly easier to type and more compact. But we can take it further. The Fluent API * style allows you to chain together multiple method calls. This even makes it desirable to operate on * single-element sets. E.g.:</p> * * <pre> * {@code * Button myButton = $(new Button("Some text")) .setUIID("Label") .addTags("cell", "row-"+rowNum, "col-"+colNum, rowNum%2==0 ? "even":"odd") .putClientProperty("row", rowNum) .putClientProperty("col", colNum) .asComponent(Button.class); * } * </pre> * * <p> * The above snippet wraps a new Button in a ComponentSelector, then uses the fluent API to apply several properties * to the button, before using {@link #asComponent()} to return the Button itself. * </p> * * <h3>API Overview</h3> * * <p>ComponentSelector includes a few different types of methods:</p> * * <ol> * <li>Wrapper methods for {@link Component}, {@link Container}, etc... to operate on all applicable components in the set.</li> * <li>Component Tree Traversal Methods to return other sets of components based on the current set. E.g. {@link #find(java.lang.String) }, {@link #getParent()}, {@link #getComponentAt(int) }, * {@link #closest(java.lang.String) }, {@link #nextSibling() }, {@link #prevSibling() }, {@link #parents(java.lang.String) }, * {@link #getComponentForm() }, and many more.</li> * <li>Effects. E.g. {@link #fadeIn() }, {@link #fadeOut() }, {@link #slideDown() }, {@link #slideUp() }, {@link #animateLayout(int) }, * {@link #animateHierarchy(int) }, etc..</li> * <li>Convenience methods to help with common tasks. E.g. {@link #$(java.lang.Runnable) } as a short-hand for {@link Display#callSerially(java.lang.Runnable) } * <li>Methods to implement {@link java.util.Set} because ComponentSelector is a set.</li> * </ol> * * * <h3>Effects</h3> * * <p>The following is an example form that demonstrates the use of ComponentSelector to * easily create effects on components in a form.</p> * * <p><script src="https://gist.github.com/shannah/536f852c3b7242a4d3106fc9e5b5d147.js"></script></p> * * <h3>Advanced Use of Tags</h3> * * <p>The following shows the use of tags to help with striping a table, and selecting rows * when clicked on.</p> * * <p><script src="https://gist.github.com/shannah/6da5728888e01abb54486a02b8c1a7c9.js"></script></p> * * <p>See full Demo App in this <a href="https://github.com/shannah/cn1-component-selector-demo">Github Repo</a></p> * * <h3>Modifying Style Properties</h3> * * <p>Modifying styles deserves special mention because components have multiple {@link Style} objects associated with them. * {@link Component#getStyle() } returns the style of the component in its current state. {@link Component#getPressedStyle() } * gets the pressed style of the component, {@link Component#getSelectedStyle() } get its selected style, etc..</p> * * <p>ComponentSelector wraps each of the {@literal getXXXStyle() } methods of {@link Component} with corresponding methods * that return proxy styles for all components in the set. {@link #getStyle() } returns a proxy {@link Style} that proxies * all of the styles returned from each of the {@link Component#getStyle()} methods in the set. {@link #getPressedStyle() } returns * a proxy for all of the pressed styles, etc..</p> * * <p>Example Modifying Text Color of All Buttons in a container when they are pressed only</p> * * <pre> * {@code * Style pressed = $("Button", myContainer).getPressedStyle(); * pressed.setFgColor(0xff0000); * } * </pre> * * <p>A slightly more elegant pattern would be to use the {@link #selectPressedStyle() } method to set the default * style for mutations to "pressed". Then we could use the fluent API of ComponentSelector to chain multiple style * mutations. E.g.: * </p> * * <pre> * {@code * $("Button", myContainer) * .selectPressedStyle() * .setFgColor(0xffffff) * .setBgColor(0x0) * .setBgTransparency(255); * } * </pre> * * <p>A short-hand for this would be to add the {@literal :pressed} pseudo-class to the selector. E.g.</p> * * <pre> * {@code * $("Button:pressed", myContainer) * .setFgColor(0xffffff) * .setBgColor(0x0) * .setBgTransparency(255); * } * </pre> * * <p>The following style pseudo-classes are supported:</p> * * <ul> * <li>{@literal :pressed} - Same as calling {@link #selectPressedStyle() }</li> * <li>{@literal :selected} - Same as calling {@link #selectSelectedStyle() }</li> * <li>{@literal :unselected} - Same as calling {@link #selectUnselectedStyle() }</li> * <li>{@literal :all} - Same as calling {@link #selectAllStyles() }</li> * <li>{@literal :*} - Alias for {@literal :all}</li> * <li>{@literal :disabled} - Same as calling {@link #selectDisabledStyle() }</li> * </ul> * * <p>You can chain calls to {@literal selectedXXXStyle()}, enabling to chain together mutations of multiple different * style properties. E.g To change the pressed foreground color, and then change the selected foreground color, you could do:</p> * * <pre> * {@code * $("Button", myContainer) * .selectPressedStyle() * .setFgColor(0x0000ff) * .selectSelectedStyle() * .setFgColor(0x00ff00); * } * </pre> * * <h3>Filtering Sets</h3> * * <p>There are many ways to remove components from a set. Obviously you can use the standard {@link java.util.Set } methods * to explicitly remove components from your set:</p> * * <pre> * {@code * ComponentSelector sel = $("Button").remove(myButton, true); * // The set of all buttons on the current form, except myButton * } * </pre> * * or * * <pre> * {@code * ComponentSelector sel = $("Button").removeAll($(".some-tag"), true); * // The set of all buttons that do NOT contain the tag ".some-tag" * } * </pre> * * <p>You could also use the {@link #filter(com.codename1.ui.ComponentSelector.Filter) } to explicitly * declare which elements should be kept, and which should be discarded:</p> * * <pre> * {@code * ComponentSelector sel = $("Button").filter(c->{ * return c.isVisible(); * }); * // The set of all buttons that are currently visible. * } * </pre> * * <h3>Tree Navigation</h3> * * <p> * One powerful aspect of working with sets of components is that you can generate very specific * sets of components using very simple queries. Consider the following queries:</p> * * <ul> * <li>{@code $(myButton1, myButton2).getParent()} - The set of parents of {@literal myButton1} and {@literal myButton2}. If they have the * same parent, then this set will only contain a single element: the common parent container. If they have different parents, then this * set will include both parent containers.</li> * <li>{@code $(myButton).getParent().find(">TextField")} - The set of siblings of {@literal myButton} that have UIID=TextField</li> * <li>{@code $(myButton).closest(".some-tag")} - The set containing the "nearest" parent container of {@literal myButton} that has * the tag ".some-tag". If there are no matching components, then this will be an empty set. This is formed by crawling up the tree * until it finds a matching component. Works the same as jQuery's {@literal closest() } method.</li> * <li>{@code $(".my-tag").getComponentAt(4)} - The set of 5th child components of containers with tag ".my-tag".</li> * </ul> * * @author shannah */ public class ComponentSelector implements Iterable<Component>, Set<Component> { private static final String PROPERTY_TAG = "com.codename1.ui.ComponentSelector#tags"; private String name; private String uiid; private String[] tags; private String[] tagsNeedles; private String state; private ComponentSelector parent; private Set<ComponentSelector> aggregateSelectors; private final Set<Component> roots; private Set<Component> results; private boolean childrenOnly = false; private Style currentStyle = null; private int currentStyleType = 0; private static final int ALL_STYLES=1; private static final int PRESSED_STYLE=2; private static final int SELECTED_STYLE=3; private static final int UNSELECTED_STYLE=4; private static final int DISABLED_STYLE=5; private Style currentStyle() { if (currentStyle == null) { switch (currentStyleType) { case ALL_STYLES: currentStyle = getAllStyles(); break; case PRESSED_STYLE: currentStyle = getPressedStyle(); break; case SELECTED_STYLE: currentStyle = getSelectedStyle(); break; case UNSELECTED_STYLE: currentStyle = getUnselectedStyle(); break; case DISABLED_STYLE: currentStyle = getDisabledStyle(); break; default: currentStyle = getStyle(); break; } } return currentStyle; } /** * Interface used for providing callbacks that receive a Component as input. */ public static interface ComponentClosure { /** * Callback to apply. * @param c Component that is passed to the closure. */ public void call(Component c); } /** * Interface used by {@link #map(com.codename1.ui.ComponentSelector.ComponentMapper) } to form a new set of * components based on the components in one set. */ public static interface ComponentMapper { /** * Maps component {@literal c } to a replacement component. * @param c The source component. * @return The component that should replace {@literal c} in the new set. */ public Component map(Component c); } /** * Interface used by {@link #filter(com.codename1.ui.ComponentSelector.Filter) } to form a new set of * components based on the components in one set. */ public static interface Filter { /** * Determines whether component {@literal c} should be included in new set. * @param c The component to test for inclusion in new set. * @return True if {@literal c } should be included in new set. False otherwise */ public boolean filter(Component c); } /** * Wraps provided components in a ComponentSelector set. * @param cmps Components to be includd in the set. * @return ComponentSelector with specified components. */ public static ComponentSelector $(Component... cmps) { return new ComponentSelector(cmps); } /** * Alias of {@link #$(com.codename1.ui.Component...) } * @param cmps * @return */ public static ComponentSelector select(Component... cmps) { return $(cmps); } private void setDirty() { currentStyle = null; } /** * Creates a ComponentInspector with the source component of the provided event. * @param e The event whose source component is added to the set. * @return A ComponentSelector with a single component - the source of the event. */ public static ComponentSelector $(ActionEvent e) { Object src = e.getSource(); if (src == null) { return new ComponentSelector(); } else if (src instanceof Component) { return new ComponentSelector((Component)src); } return new ComponentSelector(); } /** * Alias of {@link #$(com.codename1.ui.events.ActionEvent) } * @param e * @return */ public static ComponentSelector select(ActionEvent e) { return $(e); } /** * Wraps {@link Display#callSerially(java.lang.Runnable) } * @param r * @return Empty ComponentSelector. */ public static ComponentSelector $(Runnable r) { Display.getInstance().callSerially(r); return new ComponentSelector(); } /** * Alias of {@link #$(java.lang.Runnable) } * @param r * @return */ public static ComponentSelector select(Runnable r) { return $(r); } /** * Applies the given callback to each component in the set. * @param closure Callback which will be called once for each component in the set. * @return Self for chaining. */ public ComponentSelector each(ComponentClosure closure) { for (Component c : this) { closure.call(c); } return this; } /** * Creates a new set based on the elements of the current set and a mapping function * which defines the elements that should be in the new set. * @param mapper The mapper which will be called once for each element in the set. The return value * of the mapper function dictates which component should be included in the resulting set. * @return A new set of components. */ public ComponentSelector map(ComponentMapper mapper) { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { Component res = mapper.map(c); if (res != null) { out.add(res); } } return new ComponentSelector(out); } /** * Creates a new set of components formed by filtering the current set using a filter function. * @param filter The filter function called for each element in the set. If it returns true, * then the element is included in the resulting set. If false, it will not be included. * @return A new set with the results of the filter. */ public ComponentSelector filter(Filter filter) { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { boolean res = filter.filter(c); if (res) { out.add(c); } } return new ComponentSelector(out); } /** * Creates a new set of components consisting of all of the parents of components in this set. * Only parent components matching the provided selector will be included in the set. * @param selector Selector to filter the parent components. * @return New set with parents of elements in current set. */ public ComponentSelector parent(String selector) { ComponentSelector matcher = new ComponentSelector(selector, new Label()); HashSet<Component> matches = new HashSet<Component>(); for (Component c : this) { Component parent = c.getParent(); if (parent != null && matcher.match(parent)) { matches.add(parent); } } return matcher.addAll(matches, true); } /** * Creates new set of components consisting of all of the ancestors of components in this set which * match the provided selector. * @param selector The selector to filter the ancestors. * @return New set with ancestors of elements in current set. */ public ComponentSelector parents(String selector) { ComponentSelector matcher = new ComponentSelector(selector, new Label()); HashSet<Component> matches = new HashSet<Component>(); for (Component c : this) { Component parent = c.getParent(); while (parent != null) { if (matcher.match(parent)) { matches.add(parent); } parent = parent.getParent(); } } return matcher.addAll(matches, true); } /** * Creates a new set of components consistng of all "closest" ancestors of components * in this set which match the provided selector. * @param selector The selector to use to match the nearest ancestor. * @return New set with ancestors of components in current set. */ public ComponentSelector closest(String selector) { ComponentSelector matcher = new ComponentSelector(selector, new Label()); HashSet<Component> matches = new HashSet<Component>(); for (Component c : this) { Component parent = c.getParent(); while (parent != null) { if (matcher.match(parent)) { matches.add(parent); break; } parent = parent.getParent(); } } return matcher.addAll(matches, true); } /** * Creates new set consisting of the first child of each component in the current set. * @return New set with first child of each component in current set. */ public ComponentSelector firstChild() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; if (cnt.getComponentCount() > 0) { out.add(cnt.getComponentAt(0)); } } } return new ComponentSelector(out); } /** * Creates new set consisting of the last child of each component in the current set. * @return New set with last child of each component in current set. */ public ComponentSelector lastChild() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; if (cnt.getComponentCount() > 0) { out.add(cnt.getComponentAt(cnt.getComponentCount()-1)); } } } return new ComponentSelector(out); } /** * Creates set of "next" siblings of components in this set. * @return New ComponentSelector with next siblings of this set. */ public ComponentSelector nextSibling() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { int index = parent.getComponentIndex(c); if (index < parent.getComponentCount()-1) { out.add(parent.getComponentAt(index+1)); } } } return new ComponentSelector(out); } /** * Creates set of "previous" siblings of components in this set. * @return New ComponentSelector with previous siblings of this set. */ public ComponentSelector prevSibling() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { int index = parent.getComponentIndex(c); if (index > 0) { out.add(parent.getComponentAt(index-1)); } } } return new ComponentSelector(out); } /** * Animates this set of components, replacing any modified style properties of the * destination style to the components. * @param destStyle The style to apply to the components via animation. * @param duration The duration of the animation (ms) * @param callback Callback to call after animation is complete. * @return Self for chaining * @see Component#createStyleAnimation(java.lang.String, int) */ public ComponentSelector animateStyle(Style destStyle, int duration, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); AnimationManager mgr = null; for (Component c : this) { AnimationManager cmgr = c.getAnimationManager(); if (cmgr != null) { mgr = cmgr; Style sourceStyle = c.getUnselectedStyle(); destStyle.merge(sourceStyle); animations.add(c.createStyleAnimation(sourceStyle, destStyle, duration, null)); } } if (mgr != null) { ComponentAnimation anim = ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])); mgr.addAnimation(anim, new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Fade in this set of components. Prior to calling this, the component visibility * should be set to "false". This uses the default duration of 500ms. * @return Self for chaining. */ public ComponentSelector fadeIn() { return fadeIn(500); } /** * Fade in this set of components. Prior to calling this, the component visibility * should be set to "false". * @param duration The duration of the fade in. * @return Self for chaining. */ public ComponentSelector fadeIn(int duration) { return fadeIn(duration, null); } /** * Fade in this set of components. Prior to calling this, the component visibility should * be set to "false". * @param duration The duration of the fade in. * @param callback Callback to run when animation completes. * @return */ public ComponentSelector fadeIn(final int duration, final SuccessCallback<ComponentSelector> callback) { final String placeholderProperty = "com.codename1.ui.ComponentSelector#fadeOutPlaceholder"; AnimationManager mgr = null; ArrayList<ComponentAnimation> animations1 = new ArrayList<ComponentAnimation>(); final ArrayList<ComponentAnimation> animations2 = new ArrayList<ComponentAnimation>(); final ArrayList<Component> animatingComponents = new ArrayList<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { AnimationManager cmgr = c.getAnimationManager(); if (cmgr != null) { mgr = cmgr; Container placeholder = new Container(); //placeholder.getStyle().setBgColor(0xff0000); //placeholder.getStyle().setBgTransparency(255); //placeholder.setShowEvenIfBlank(true); c.putClientProperty(placeholderProperty, placeholder); Component.setSameHeight(placeholder, c); Component.setSameWidth(placeholder, c); $(placeholder) .setMargin(c.getStyle().getMarginTop(), c.getStyle().getMarginRight(false), c.getStyle().getMarginBottom(), c.getStyle().getMarginLeft(false)) .setPadding(c.getStyle().getPaddingTop(), c.getStyle().getPaddingRight(false), c.getStyle().getPaddingBottom(), c.getStyle().getPaddingLeft(false)); //System.out.println("Placeholder height "+c.getHeight()); //parent.replace(c, placeholder, false); //c.setHidden(false); ComponentAnimation a = parent.createReplaceTransition(c, placeholder, CommonTransitions.createEmpty()); animations1.add(a); animatingComponents.add(c); } //centerBackground.add(BorderLayout.CENTER, boxy); } } if (mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations1.toArray(new ComponentAnimation[animations1.size()])), new Runnable() { public void run() { AnimationManager mgr = null; for (final Component c : animatingComponents) { Container placeholder = (Container)c.getClientProperty(placeholderProperty); if (placeholder != null) { //System.out.println("Placeholder height after replace "+(c.getHeight() + c.getStyle().getMarginBottom() + c.getStyle().getMarginTop())); //System.out.println("Placeholder not null"); c.putClientProperty(placeholderProperty, null); AnimationManager cmgr = placeholder.getAnimationManager(); if (cmgr != null) { //System.out.println("Animation manager not null"); mgr = cmgr; c.setVisible(true); Container parent = placeholder.getParent(); if (parent != null) { //System.out.println("Parent not null"); ComponentAnimation a = parent.createReplaceTransition(placeholder, c, CommonTransitions.createFade(duration)); animations2.add(a); } } } } if (mgr != null) { final AnimationManager fmgr = mgr; $(new Runnable() { public void run() { fmgr.addAnimation(ComponentAnimation.compoundAnimation(animations2.toArray(new ComponentAnimation[animations2.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } }); } } }); } return this; } /** * Fades in this component and blocks until animation is complete. * @return Self for chaining. */ public ComponentSelector fadeInAndWait() { return fadeInAndWait(500); } /** * Fades in this component and blocks until animation is complete. * @param duration The duration of the animation. * @return Self for chaining. */ public ComponentSelector fadeInAndWait(final int duration) { final String placeholderProperty = "com.codename1.ui.ComponentSelector#fadeOutPlaceholder"; AnimationManager mgr = null; ArrayList<ComponentAnimation> animations1 = new ArrayList<ComponentAnimation>(); final ArrayList<ComponentAnimation> animations2 = new ArrayList<ComponentAnimation>(); final ArrayList<Component> animatingComponents = new ArrayList<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { AnimationManager cmgr = c.getAnimationManager(); if (cmgr != null) { mgr = cmgr; Container placeholder = new Container(); //placeholder.getStyle().setBgColor(0xff0000); //placeholder.getStyle().setBgTransparency(255); //placeholder.setShowEvenIfBlank(true); c.putClientProperty(placeholderProperty, placeholder); Component.setSameHeight(placeholder, c); Component.setSameWidth(placeholder, c); $(placeholder) .setMargin(c.getStyle().getMarginTop(), c.getStyle().getMarginRight(false), c.getStyle().getMarginBottom(), c.getStyle().getMarginLeft(false)) .setPadding(c.getStyle().getPaddingTop(), c.getStyle().getPaddingRight(false), c.getStyle().getPaddingBottom(), c.getStyle().getPaddingLeft(false)); //System.out.println("Placeholder height "+c.getHeight()); //parent.replace(c, placeholder, false); //c.setHidden(false); ComponentAnimation a = parent.createReplaceTransition(c, placeholder, CommonTransitions.createEmpty()); animations1.add(a); animatingComponents.add(c); } //centerBackground.add(BorderLayout.CENTER, boxy); } } if (mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations1.toArray(new ComponentAnimation[animations1.size()]))); for (final Component c : animatingComponents) { Container placeholder = (Container)c.getClientProperty(placeholderProperty); if (placeholder != null) { //System.out.println("Placeholder height after replace "+(c.getHeight() + c.getStyle().getMarginBottom() + c.getStyle().getMarginTop())); //System.out.println("Placeholder not null"); c.putClientProperty(placeholderProperty, null); AnimationManager cmgr = placeholder.getAnimationManager(); if (cmgr != null) { //System.out.println("Animation manager not null"); mgr = cmgr; c.setVisible(true); Container parent = placeholder.getParent(); if (parent != null) { //System.out.println("Parent not null"); ComponentAnimation a = parent.createReplaceTransition(placeholder, c, CommonTransitions.createFade(duration)); animations2.add(a); } } } } if (mgr != null) { mgr.addAnimationAndBlock( ComponentAnimation.compoundAnimation(animations2.toArray(new ComponentAnimation[animations2.size()])) ); } } return this; } /** * Returns true if the first component in this set is visible. * @return True if first component in this set is visible. * @see Component#isVisible() */ public boolean isVisible() { for (Component c : this) { return c.isVisible(); } return false; } /** * Returns true if first component in this set is hidden. * @return True if first component in set is hidden. * @see Component#isHidden() */ public boolean isHidden() { for (Component c : this) { return c.isHidden(); } return false; } /** * Fades out components in this set. Uses default duration of 500ms. * @return Self for chaining. */ public ComponentSelector fadeOut() { return fadeOut(500); } /** * Fades out components in this set. * @param duration Duration of animation. * @return Self for chaining. */ public ComponentSelector fadeOut(int duration) { return fadeOut(duration, null); } /** * Fades out components in this set. * @param duration Duration of animation. * @param callback Callback to run when animation completes. * @return Self for chaining. */ public ComponentSelector fadeOut(int duration, final SuccessCallback<ComponentSelector> callback) { final String placeholderProperty = "com.codename1.ui.ComponentSelector#fadeOutPlaceholder"; AnimationManager mgr = null; ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); final ArrayList<Component> animatingComponents = new ArrayList<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { AnimationManager cmgr = c.getAnimationManager(); if (cmgr != null) { mgr = cmgr; Container placeholder = new Container(); //placeholder.setShowEvenIfBlank(true); c.putClientProperty(placeholderProperty, placeholder); Component.setSameHeight(placeholder, c); Component.setSameWidth(placeholder, c); $(placeholder) .setMargin(c.getStyle().getMarginTop(), c.getStyle().getMarginRight(false), c.getStyle().getMarginBottom(), c.getStyle().getMarginLeft(false)) .setPadding(c.getStyle().getPaddingTop(), c.getStyle().getPaddingRight(false), c.getStyle().getPaddingBottom(), c.getStyle().getPaddingLeft(false)); ComponentAnimation a = parent.createReplaceTransition(c, placeholder, CommonTransitions.createFade(duration)); animations.add(a); animatingComponents.add(c); } //centerBackground.add(BorderLayout.CENTER, boxy); } } if (mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { for (final Component c : animatingComponents) { //c.setHidden(true); c.setVisible(false); final Container placeholder = (Container)c.getClientProperty(placeholderProperty); c.putClientProperty(placeholderProperty, null); if (placeholder != null) { Container parent = placeholder.getParent(); /* if (parent == null) { System.out.println("Deferring replace back"); $(new Runnable() { public void run() { Container parent = placeholder.getParent(); if (parent != null) { System.out.println("Found parent after deferral"); parent.replace(placeholder, c, CommonTransitions.createEmpty()); } } }); } else { */ if (parent != null) { parent.replace(placeholder, c, CommonTransitions.createEmpty()); } //} } } if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Hide the matched components with a sliding motion. * @param duration Duration of animation * @return Self for chaining. */ public ComponentSelector slideUp(int duration) { return slideUp(duration, null); } /** * Hide the matched elements with a sliding motion. * @param duration Duration of animation. * @param callback Callback to run when animation completes * @return Self for chaining. */ public ComponentSelector slideUp(int duration, final SuccessCallback<ComponentSelector> callback) { final ArrayList<Component> animatedComponents = new ArrayList<Component>(); for (Component c : this) { c.setHeight(0); animatedComponents.add(c); } getParent().animateUnlayout(duration, 255, new SuccessCallback<ComponentSelector>() { public void onSucess(ComponentSelector value) { for (Component c : animatedComponents) { c.setVisible(false); } getParent().revalidate(); if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); return this; } /** * Hide the matched elements with a sliding motion. Blocks until animation is complete. * @param duration Duration of animation. * @return Self for chaining. */ public ComponentSelector slideUpAndWait(int duration) { for (Component c : this) { c.setHeight(0); } getParent().animateUnlayoutAndWait(duration, 255); return this; } /** * Display the matched elements with a sliding motion. Uses default duration of 500ms * @return Self for chaining. */ public ComponentSelector slideDown() { return slideDown(500); } /** * Hide the matched elements with a sliding motion. Uses default duration of 500ms * @return Self for chaining. */ public ComponentSelector slideUp() { return slideUp(500); } /** * Display the matched elements with a sliding motion. * @param duration Duration of animation. * @return Self for chaining. */ public ComponentSelector slideDown(int duration) { return slideDown(duration, null); } /** * Display the matched elements with a sliding motion. * @param duration Duration of animation. * @param callback Callback to run when animation completes. * @return Self for chaining. */ public ComponentSelector slideDown(final int duration, final SuccessCallback<ComponentSelector> callback) { for (Component c : this) { c.setHeight(0); c.setVisible(true); } getParent().animateLayout(duration, callback); return this; } /** * Display the matched elements with a sliding motion. Blocks until animation is complete. * @param duration Duration of animation. * @return Self for chaining. */ public ComponentSelector slideDownAndWait(final int duration) { final ArrayList<Component> animatedComponents = new ArrayList<Component>(); for (Component c : this) { c.setHeight(0); c.setVisible(true); animatedComponents.add(c); } getParent().animateLayoutAndWait(duration); return this; } /** * Hide the matched elements by fading them to transparent. Blocks thread until animation is complete. * @param duration Duration of animation. * @return Self for chaining. */ public ComponentSelector fadeOutAndWait(int duration) { final String placeholderProperty = "com.codename1.ui.ComponentSelector#fadeOutPlaceholder"; AnimationManager mgr = null; ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); final ArrayList<Component> animatingComponents = new ArrayList<Component>(); for (Component c : this) { Container parent = c.getParent(); if (parent != null) { AnimationManager cmgr = c.getAnimationManager(); if (cmgr != null) { mgr = cmgr; Container placeholder = new Container(); //placeholder.setShowEvenIfBlank(true); c.putClientProperty(placeholderProperty, placeholder); Component.setSameHeight(placeholder, c); Component.setSameWidth(placeholder, c); $(placeholder) .setMargin(c.getStyle().getMarginTop(), c.getStyle().getMarginRight(false), c.getStyle().getMarginBottom(), c.getStyle().getMarginLeft(false)) .setPadding(c.getStyle().getPaddingTop(), c.getStyle().getPaddingRight(false), c.getStyle().getPaddingBottom(), c.getStyle().getPaddingLeft(false)); ComponentAnimation a = parent.createReplaceTransition(c, placeholder, CommonTransitions.createFade(duration)); animations.add(a); animatingComponents.add(c); } //centerBackground.add(BorderLayout.CENTER, boxy); } } if (mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); for (final Component c : animatingComponents) { c.setVisible(false); final Container placeholder = (Container)c.getClientProperty(placeholderProperty); c.putClientProperty(placeholderProperty, null); if (placeholder != null) { Container parent = placeholder.getParent(); if (parent != null) { parent.replace(placeholder, c, CommonTransitions.createEmpty()); } } } } return this; } /** * Replaces the matched components within respective parents with replacements defined by the provided mapper. Replacements * are replaced in the UI itself (i.e. {@code c.getParent().replace(c, replacement)}) with an empty * transition. * @param mapper Mapper that defines the replacements for each component in the set. If the mapper returns * the input component, then no change is made for that component. A null return value cause the component * to be removed from its parent. Returning a Component results in that component replacing the original component * within its parent. * @return A new ComponentSelector with the replacement components. */ public ComponentSelector replace(ComponentMapper mapper) { return replace(mapper, CommonTransitions.createEmpty()); } /** * Replaces the matched components within respective parents with replacements defined by the provided mapper. Replacements * are replaced in the UI itself (i.e. {@code c.getParent().replace(c, replacement)}) with the provided transition. * @param mapper Mapper that defines the replacements for each component in the set. If the mapper returns * the input component, then no change is made for that component. A null return value cause the component * to be removed from its parent. Returning a Component results in that component replacing the original component * within its parent. * @param t Transition to use for replacements. * @return A new ComponentSelector with the replacement components. */ public ComponentSelector replace(ComponentMapper mapper, Transition t) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); HashSet<Component> replacements = new HashSet<Component>(); for (Component c : this) { Container parent = c.getParent(); Component replacement = mapper.map(c); if (parent != null) { if (replacement != c) { if (replacement != null) { animations.add(parent.createReplaceTransition(c, replacement, t.copy(false))); } else { c.remove(); } } } if (replacement != null) { replacements.add(replacement); } } AnimationManager mgr = getAnimationManager(); if (mgr != null && animations.size() > 0) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return new ComponentSelector(replacements); } /** * Replaces the matched components within respective parents with replacements defined by the provided mapper. Replacements * are replaced in the UI itself (i.e. {@code c.getParent().replace(c, replacement)}) with the provided transition. * Blocks the thread until the transition animation is complete. * @param mapper Mapper that defines the replacements for each component in the set. If the mapper returns * the input component, then no change is made for that component. A null return value cause the component * to be removed from its parent. Returning a Component results in that component replacing the original component * within its parent. * @param t * @return A new ComponentSelector with the replacement components. */ public ComponentSelector replaceAndWait(ComponentMapper mapper, Transition t) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); HashSet<Component> replacements = new HashSet<Component>(); for (Component c : this) { Container parent = c.getParent(); Component replacement = mapper.map(c); if (parent != null) { if (replacement != c) { if (replacement != null) { animations.add(parent.createReplaceTransition(c, replacement, t.copy(false))); } else { c.remove(); } } } if (replacement != null) { replacements.add(replacement); } } AnimationManager mgr = getAnimationManager(); if (mgr != null && animations.size() > 0) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return new ComponentSelector(replacements); } /** * Creates a component selector that wraps the provided components. The provided * components are treated as the "results" of this selector. Not the roots. However * you can use {@link #find(java.lang.String) } to perform a query using this selector * as the roots. * @param cmps Components to add to this selector results. */ public ComponentSelector(Component... cmps) { this.roots = new HashSet<Component>(); this.results = new HashSet<Component>(); for (Component cmp : cmps) { this.results.add(cmp); } } /** * Creates a new ComponentSelector with the provided set of components. * @param cmps The components to include in the set. * @return ComponentSelector with provided components. */ public static ComponentSelector $(Set<Component> cmps) { return new ComponentSelector(cmps); } /** * Alias of {@link #$(java.util.Set) } * @param cmps * @return */ public static ComponentSelector select(Set<Component> cmps) { return $(cmps); } /** * Creates a component selector that wraps the provided components. The provided * components are treated as the "results" of this selector. Not the roots. However * you can use {@link #find(java.lang.String) } to perform a query using this selector * as the roots. * @param cmps Components to add to this selector results. */ public ComponentSelector(Set<Component> cmps) { this.roots = new HashSet<Component>(); this.results = new HashSet<Component>(); this.results.addAll(cmps); } /** * Creates a new ComponentSelector with the components matched by the provided selector. The current form * is used as the root for searches. Will throw a runtime exception if there is no current form. * @param selector A selector string that defines which components to include in the * set. * @return ComponentSelector with matching components. */ public static ComponentSelector $(String selector) { return new ComponentSelector(selector); } /** * Alias of {@link #$(java.lang.String) } * @param selector * @return */ public static ComponentSelector select(String selector) { return $(selector); } /** * Creates a selector that will query the current form. If there is no * current form, then this selector will have no roots. * <p>Generally it is better to provide a root explicitly using {@link ComponentSelector#ComponentSelector(java.lang.String, com.codename1.ui.Component...) * to ensure that the selector has a tree to walk down. * @param selector The selector string. */ public ComponentSelector(String selector) { this.roots = new HashSet<Component>(); Form f = Display.getInstance().getCurrent(); if (f != null) { this.roots.add(f); } else { throw new RuntimeException("Attempt to create selector on current form, but there is no current form. Best practice is to explicitly provide a root for your ComponentSelector."); } parse(selector); } /** * Creates a ComponentSelector with the components matched by the provided selector in the provided * roots' subtrees. * @param selector Selector string to define which components will be included in the set. * @param roots Roots for the selector to search. Only components within the roots' subtrees will be included in the set. * @return ComponentSelector with matching components. */ public static ComponentSelector $(String selector, Component... roots) { return new ComponentSelector(selector, roots); } /** * Alias of {@link #$(java.lang.String, com.codename1.ui.Component...) } * @param selector * @param roots * @return */ public static ComponentSelector select(String selector, Component... roots) { return $(selector, roots); } /** * Creates a selector with the provided roots. This will only search through the subtrees * of the provided roots to find results that match the provided selector string. * @param selector The selector string * @param roots The roots for this selector. */ public ComponentSelector(String selector, Component... roots) { this.roots = new HashSet<Component>(); for (Component root : roots) { this.roots.add(root); } parse(selector); } /** * Creates a ComponentSelector with the components matched by the provided selector in the provided * roots' subtrees. * @param selector Selector string to define which components will be included in the set. * @param roots Roots for the selector to search. Only components within the roots' subtrees will be included in the set. * @return ComponentSelector with matching components. */ public static ComponentSelector $(String selector, Collection<Component> roots) { return new ComponentSelector(selector, roots); } /** * Alias of {@link #$(java.lang.String, java.util.Collection) } * @param selector * @param roots * @return */ public static ComponentSelector select(String selector, Collection<Component> roots) { return $(selector, roots); } /** * Creates a selector with the provided roots. This will only search through the subtrees * of the provided roots to find results that match the provided selector string. * @param selector The selector string * @param roots The roots for this selector. */ public ComponentSelector(String selector, Collection<Component> roots) { this.roots = new HashSet<Component>(); this.roots.addAll(roots); parse(selector); } /** * Uses the results of this selector as the roots to create a new selector with * the provided selector string. * @param selector The selector string. * @return A new ComponentSelector with the results of the query. */ public ComponentSelector find(String selector) { return new ComponentSelector(selector, resultsImpl()); } private void parse(String selector) { selector = selector.trim(); if (selector.indexOf(",") != -1) { // this is an aggregate selector String[] parts = Util.split(selector, ","); aggregateSelectors = new HashSet<ComponentSelector>(); for (String part : parts) { part = part.trim(); if (part.length() == 0) { continue; } aggregateSelectors.add(new ComponentSelector(part, roots)); } return; } String[] parts = Util.split(selector, " "); int len = parts.length; if (len > 1) { StringBuilder parentSelector = new StringBuilder(); for (int i=0; i<len; i++) { if (">".equals(parts[i])) { if (i < len-1) { parts[i] = ">" + parts[i+1].trim(); for (int j=i+1; j<len-1; j++) { parts[j] = parts[j+1]; } len--; parts[len] = null; } else { throw new IllegalArgumentException("Failed to parse selector. Selector cannot end with '>'"); } } if (i>0 && i < len-1) { parentSelector.append(" "); } if (i < len-1) { parentSelector.append(parts[i]); } if (i == len-1) { selector = parts[i]; } } if (parentSelector.length() > 0) { parent = new ComponentSelector(parentSelector.toString(), roots); roots.clear(); } } if (selector.indexOf(">") == 0) { childrenOnly = true; selector = selector.substring(1).trim(); } if (selector.indexOf(",") != -1) { throw new IllegalArgumentException("Invalid character in selector "+selector); } else { ComponentSelector out = this; selector = selector.trim(); int pos; if ((pos = selector.indexOf(":")) != -1) { out.state = selector.substring(pos+1); selector = selector.substring(0, pos); } if ((pos = selector.indexOf(".")) != -1) { out.tags = Util.split(selector.substring(pos+1), "."); len = out.tags.length; out.tagsNeedles = new String[len]; String[] needles = out.tagsNeedles; String[] tags = out.tags; for (int i=0; i<len; i++) { needles[i] = " " + tags[i] + " "; // Will make it easier to match against components' tags. } selector = selector.substring(0, pos); } if ((pos = selector.indexOf("#")) >= 0) { out.name = selector.substring(pos+1); selector = selector.substring(0, pos); } if (selector.length() > 0 && !"*".equals(selector)) { out.uiid = selector; } if (state != null) { if ("pressed".equals(state)) { currentStyleType = PRESSED_STYLE; } else if ("selected".equals(state)) { currentStyleType = SELECTED_STYLE; } else if ("unselected".equals(state)) { currentStyleType = UNSELECTED_STYLE; } else if ("disabled".equals(state)) { currentStyleType = DISABLED_STYLE; } else if ("all".equals(state) || "*".equals(state)) { currentStyleType = ALL_STYLES; } } //return out; } } private boolean match(Component c) { if (name != null && !name.equals(c.getName())) { return false; } if (uiid != null && !uiid.equals(c.getUIID())) { return false; } if (tags != null) { String ctags = (String)c.getClientProperty(PROPERTY_TAG); if (ctags != null) { for (String ctag : tagsNeedles) { if (ctags.indexOf(ctag) == -1) { return false; } } } else { return false; } } return true; } /** * Returns the results of this selector. * @return */ public Iterator<Component> iterator() { return resultsImpl().iterator(); } private Set<Component> resultsImpl() { if (results == null) { results = new HashSet<Component>(); if (aggregateSelectors != null) { for (ComponentSelector sel : aggregateSelectors) { results.addAll(sel.resultsImpl()); } return results; } if (parent != null) { roots.clear(); roots.addAll(parent.resultsImpl()); } for (Component root : roots) { if (childrenOnly) { if (root instanceof Container) { Container cnt = (Container)root; for (Component child : cnt) { if (match(child)) { results.add(child); } } } } else { if (root instanceof Container) { Container cnt = (Container)root; for (Component child : cnt) { resultsImpl(results, child); } } } } } return results; } private Set<Component> resultsImpl(Set<Component> out, Component root) { if (match(root)) { out.add(root); } if (root instanceof Container) { Container cnt = (Container)root; for (Component child : cnt) { resultsImpl(out, child); } } return out; } /** * Gets a proxy style that wraps the result of {@link Component#getStyle() } of each component in set. * @return */ public Style getStyle() { HashSet<Style> out = new HashSet<Style>(); for (Component c : this) { out.add(c.getStyle()); } return Style.createProxyStyle(out.toArray(new Style[out.size()])); } /** * Gets a style object for the given component that can be used to modify the * component's styles. This takes into account any state-pseudo classes that * were used to create this selector so that the style returned will be appropriate. * * <p>E.g. <pre> * {@code * * ComponentSelector sel = new ComponentSelector("Button:pressed"); * Style style = sel.getStyle(sel.get(0)); * // This should be equivalent to sel.get(0).getPressedStyle() * * sel = new ComponentSelector("Button"); * style = sel.getStyle(sel.get(0)); * // This should be equivalent to sel.get(0).getAllStyles() * * sel = new ComponentSelector("Button:pressed, Button:selected"); * style = sel.getStyle(sel.get(0)); * // This should be same as * // Style.createProxyStyle(sel.get(0).getPressedStyle(), sel.get(0).getSelectedStyle()) * } * </pre> * @param component The component whose style object we wish to obtain. * @return A style object that will allow us to modify the style of the given component. */ public Style getStyle(Component component) { switch (currentStyleType) { case SELECTED_STYLE: return component.getSelectedStyle(); case UNSELECTED_STYLE: return component.getUnselectedStyle(); case DISABLED_STYLE: return component.getDisabledStyle(); case PRESSED_STYLE: return component.getPressedStyle(); case ALL_STYLES: return component.getAllStyles(); default: return component.getStyle(); } } /** * Returns a proxy style for all of the selected styles of the components in this set. * @return Proxy style to easily change properties of the selected styles of all * components in this set. */ public Style getSelectedStyle() { ArrayList<Style> styles = new ArrayList<Style>(); for (Component c : this) { styles.add(c.getSelectedStyle()); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Sets the current style to the selected style. Style mutation methods called after * calling this method will modify the components' "selected style". * @return Self for chaining. * @see Component#getSelectedStyle() */ public ComponentSelector selectSelectedStyle() { currentStyle = getSelectedStyle(); currentStyleType = SELECTED_STYLE; return this; } /** * Sets the current style to the unselected style. Style mutation methods called after * calling this method will modify the components' "unselected style". * @return Self for chaining. * @see Component#getUnselectedStyle() */ public ComponentSelector selectUnselectedStyle() { currentStyle = getUnselectedStyle(); currentStyleType = UNSELECTED_STYLE; return this; } /** * Sets the current style to the pressed style. Style mutation methods called after * calling this method will modify the components' "pressed style". * @return Self for chaining. * @see Component#getPressedStyle() */ public ComponentSelector selectPressedStyle() { currentStyle = getPressedStyle(); currentStyleType = PRESSED_STYLE; return this; } /** * Sets the current style to the disabled style. Style mutation methods called after * calling this method will modify the components' "disabled style". * @return Self for chaining. * @see Component#getDisabledStyle() */ public ComponentSelector selectDisabledStyle() { currentStyle = getDisabledStyle(); currentStyleType = DISABLED_STYLE; return this; } /** * Sets the current style to each component's ALL STYLES proxy style. Style mutation methods called after * calling this method will modify the components' "all styles" proxy style. * @return Self for chaining. * @see Component#getAllStyles() */ public ComponentSelector selectAllStyles() { currentStyle = getAllStyles(); currentStyleType = ALL_STYLES; return this; } /** * Returns a proxy style for all of the unselected styles of the components in this set. * @return Proxy style to easily change properties of the unselected styles of all * components in this set. */ public Style getUnselectedStyle() { ArrayList<Style> styles = new ArrayList<Style>(); for (Component c : this) { styles.add(c.getUnselectedStyle()); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Returns a proxy style for all of the pressed styles of the components in this set. * @return Proxy style to easily change properties of the pressed styles of all * components in this set. */ public Style getPressedStyle() { ArrayList<Style> styles = new ArrayList<Style>(); for (Component c : this) { styles.add(c.getPressedStyle()); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Returns a proxy style for all of the disabled styles of the components in this set. * @return Proxy style to easily change properties of the disabled styles of all * components in this set. */ public Style getDisabledStyle() { ArrayList<Style> styles = new ArrayList<Style>(); for (Component c : this) { styles.add(c.getDisabledStyle()); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Returns a proxy style for all of the "all" styles of the components in this set. * @return Proxy style to easily change properties of the "all" styles of all * components in this set. */ public Style getAllStyles() { ArrayList<Style> styles = new ArrayList<Style>(); for (Component c : this) { styles.add(c.getAllStyles()); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Returns number of results found. * @return */ public int size() { return resultsImpl().size(); } /** * * @return True if there were no results. */ public boolean isEmpty() { return resultsImpl().isEmpty(); } /** * Checks if an object is contained in result set. * @param o * @return */ public boolean contains(Object o) { return resultsImpl().contains(o); } /** * Returns results as an array. * @return */ public Object[] toArray() { return resultsImpl().toArray(); } /** * Returns results as an array. * @param <T> * @param a * @return */ public <T> T[] toArray(T[] a) { return resultsImpl().toArray(a); } /** * Explicitly adds a component to the result set. * @param e * @return True on success */ public boolean add(Component e) { setDirty(); return resultsImpl().add(e); } /** * Appends a child component to the first container in this set. Same as calling * {@link Container#add(com.codename1.ui.Component) } padding {@literal child} on first container * in this set. * @param child Component to add to container. * @return Self for chaining. */ public ComponentSelector append(Component child) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.add(child); return this; } } return this; } /** * Appends a child component to the first container in this set. Same as calling * {@link Container#add(java.lang.Object, com.codename1.ui.Component) } padding {@literal child} on first container * in this set. * @param constraint * @param child * @return */ public ComponentSelector append(Object constraint, Component child) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.add(constraint, child); return this; } } return this; } /** * Append a child element to each container in this set. The {@literal mapper} callback * will receive a Container as input (that is the parent to be added to), and should return * a Component that is to be added to it. If the mapper returns null, then nothing is * added to that container. * @param mapper * @return */ public ComponentSelector append(ComponentMapper mapper) { for (Component c : this) { if (c instanceof Container) { Component child = mapper.map(c); if (child != null) { ((Container)c).add(child); } } } return this; } /** * Append a child element to each container in this set. The {@literal mapper} callback * will receive a Container as input (that is the parent to be added to), and should return * a Component that is to be added to it. If the mapper returns null, then nothing is * added to that container. * @param constraint * @param mapper * @return */ public ComponentSelector append(Object constraint, ComponentMapper mapper) { for (Component c : this) { if (c instanceof Container) { Component child = mapper.map(c); ((Container)c).add(constraint, child); } } return this; } /** * Fluent API wrapper for {@link #add(com.codename1.ui.Component) } * @param e Component to add to set. * @param chain Dummy argument so that this version would have a different signature than {@link Set#add(java.lang.Object) } * @return Self for chaining. */ public ComponentSelector add(Component e, boolean chain) { add(e); return this; } /** * Explicitly removes a component from the result set. * @param o * @return Self for chaining. */ public boolean remove(Object o) { setDirty(); return resultsImpl().remove(o); } /** * Fluent API wrapper for {@link #remove(java.lang.Object) }. * @param o The component to remove from set. * @param chain Dummy argument so that this version would have a different signature than {@link Set#remove(java.lang.Object) } * @return Self for chaining. */ public ComponentSelector remove(Object o, boolean chain) { remove(o); return this; } /** * Checks if the result set contains all of the components found in the provided * collection. * @param c * @return */ public boolean containsAll(Collection<?> c) { return resultsImpl().containsAll(c); } /** * Adds all components in the given collection to the result set. * @param c * @return */ public boolean addAll(Collection<? extends Component> c) { setDirty(); return resultsImpl().addAll(c); } /** * Fluent API wrapper for {@link #addAll(java.util.Collection) }. * @param c The set of components to add to this set. * @param chain Dummy argument so that this version would have a different signature than {@link #addAll(java.util.Collection) } * @return Self for chaining. */ public ComponentSelector addAll(Collection<? extends Component> c, boolean chain) { addAll(c); return this; } /** * Returns the first component in this set. This is useful for single component sets (e.g. {@code $(new Label()).setFgColor(0xff0000).asComponent() }). * * @return The first component in this set. */ public Component asComponent() { for (Component c : this) { return c; } return null; } /** * Returns the first component in this set. This is useful for single component sets (e.g. {@code $(new Label()).setFgColor(0xff0000).asComponent(Label.class) }). * * @param <T> The type of component to return * @param type The type of component that is expected to be returned. * @return The first component in this set. */ public <T extends Component> T asComponent(Class<T> type) { return (T)asComponent(); } /** * Returns the components of this set as a List. Note that order of elements is not maintained since * ComponentSelector is a set (i.e. has no notion of element order). * @return The components in this set as a list. */ public java.util.List<Component> asList() { ArrayList<Component> out = new ArrayList<Component>(); out.addAll(this); return out; } /** * Retains only elements of the result set that are contained in the provided collection. * @param c * @return */ public boolean retainAll(Collection<?> c) { setDirty(); return resultsImpl().retainAll(c); } /** * Fluent API wrapper for {@link #retainAll(java.util.Collection) } * @param c The collection to retain. * @param chain Dummy arg. * @return Self for chaining. */ public ComponentSelector retainAll(Collection<?> c, boolean chain) { retainAll(c); return this; } /** * Removes all of the components in the provided collection from the result set. * @param c * @return */ public boolean removeAll(Collection<?> c) { setDirty(); return resultsImpl().removeAll(c); } /** * Fluent API wrapper for {@link #removeAll(java.util.Collection) } * @param c Collection with components to remove, * @param chain Dummy arg. * @return Self for chaining. */ public ComponentSelector removeAll(Collection<?> c, boolean chain) { removeAll(c); return this; } /** * Clears the result set. */ public void clear() { setDirty(); resultsImpl().clear(); } /** * Fluent API wrapper for (@link #clear()} * @param chain Dummy arg * @return Self for chaining. */ public ComponentSelector clear(boolean chain) { clear(); return this; } @Override public String toString() { return "ComponentSelector{ name="+name+", uiid="+uiid+", tags="+Arrays.toString(tags)+", roots="+roots+", parent="+parent+", results = "+results+"}"; } /** * Adds the given tags to all elements in the result set. * @param tags Tags to add. * @return Self for chaining. */ public ComponentSelector addTags(String... tags) { for (Component c : this) { String existing = (String)c.getClientProperty(PROPERTY_TAG); if (existing == null) { existing = ""; } for (String tag : tags) { if (existing.indexOf(" "+tag+" ") == -1) { existing += " "+tag+" "; } } c.putClientProperty(PROPERTY_TAG, existing); } return this; } /** * Removes the given tags from all elements in the result set. * @param tags * @return */ public ComponentSelector removeTags(String... tags) { for (Component c : this) { String existing = (String)c.getClientProperty(PROPERTY_TAG); if (existing == null) { continue; } Set<String> existingSet = new HashSet<String>(); String[] existingStrs = Util.split(" ", existing); for (String existingStr : existingStrs) { existingStr = existingStr.trim(); if (existingStr.length() > 0) { existingSet.add(existingStr); } } for (String tag : tags) { existingSet.add(tag); } existing = ""; if (existingSet.isEmpty()) { c.putClientProperty(PROPERTY_TAG, null); continue; } for (String tag : existingSet) { existing += " " + tag + " "; } c.putClientProperty(PROPERTY_TAG, existing); } return this; } /** * Gets the set of all "parent" components of components in the result set. * @return New Component selector with respective parents of the components in the * current result set. */ public ComponentSelector getParent() { HashSet<Component> parents = new HashSet<Component>(); for (Component c : this) { Component parent = c.getParent(); //System.out.println("Parent is "+parent); if (parent != null) { parents.add(parent); } } //System.out.println(resultsImpl() + "Creating parent component selector with "+parents); return new ComponentSelector(parents); } /** * Wrapper for {@link Component#setSameWidth(com.codename1.ui.Component...) }. Passes all * components in the result set as parameters of this method, effectively making them all the * same width. * @return */ public ComponentSelector setSameWidth() { Component.setSameWidth(toArray(new Component[size()])); return this; } /** * Wrapper for {@link Component#setSameHeight(com.codename1.ui.Component...) }. Passes all * components in the result set as parameters of this method, effectively making them all the * same height. * @return */ public ComponentSelector setSameHeight() { Component.setSameHeight(toArray(new Component[size()])); return this; } /** * Wrapper for {@link Component#clearClientProperties() }. * @return Self for Chaining. */ public ComponentSelector clearClientProperties() { for (Component c : this) { c.clearClientProperties(); } return this; } /** * Wrapper for {@link Component#putClientProperty(java.lang.String, java.lang.Object) * @param key Property key * @param value Property value * @return Self for chaining. */ public ComponentSelector putClientProperty(String key, Object value) { for (Component c : this) { c.putClientProperty(key, value); } return this; } /** * Gets a client property from the first component in the set. Wraps {@link Component#getClientProperty(java.lang.String) } * @param key The key of the client property to retrieve. * @return The value of the client property. */ public Object getClientProperty(String key) { for (Component c : this) { return c.getClientProperty(key); } return null; } /** * Wrapper for {@link Component#setDirtyRegion(com.codename1.ui.geom.Rectangle) } * @param rect Dirty region * @return Self for chaining. */ public ComponentSelector setDirtyRegion(Rectangle rect) { for (Component c : this) { c.setDirtyRegion(rect); } return this; } /** * Wrapper for {@link Component#setVisible(boolean) } * @param visible True to make all components in result set visible. False for hidden. * @return Self for chaining. */ public ComponentSelector setVisible(boolean visible) { for (Component c : this) { c.setVisible(visible); } return this; } /** * Wrapper for {@link Component#setX(int) } * @param x * @return */ public ComponentSelector setX(int x) { for (Component c : this) { c.setX(x); } return this; } /** * Wrapper for {@link Component#setY(int) } * @param y * @return */ public ComponentSelector setY(int y) { for (Component c : this) { c.setY(y); } return this; } /** * Wrapper for {@link Component#setWidth(int) } * @param width * @return */ public ComponentSelector setWidth(int width) { for (Component c : this) { c.setWidth(width); } return this; } /** * Wrapper for {@link Component#setHeight(int) } * @param height * @return */ public ComponentSelector setHeight(int height) { for (Component c : this) { c.setHeight(height); } return this; } /** * Wrapper for {@link Component#setPreferredSize(com.codename1.ui.geom.Dimension) } * @param dim * @return */ public ComponentSelector setPreferredSize(Dimension dim) { for (Component c : this) { c.setPreferredSize(dim); } return this; } /** * Wrapper for {@link Component#setPreferredH(int) } * @param h * @return */ public ComponentSelector setPreferredH(int h) { for (Component c : this) { c.setPreferredH(h); } return this; } /** * Wrapper for {@link Component#setPreferredW(int) } * @param w * @return */ public ComponentSelector setPreferredW(int w) { for (Component c : this) { c.setPreferredW(w); } return this; } /** * Wrapper for {@link Component#setScrollSize} * @param size * @return */ public ComponentSelector setScrollSize(Dimension size) { for (Component c : this) { c.setScrollSize(size); } return this; } /** * Wrapper for {@link Component#setSize(com.codename1.ui.geom.Dimension) } * @param size * @return */ public ComponentSelector setSize(Dimension size) { for (Component c : this) { c.setSize(size); } return this; } /** * Wrapper for {@link Component#setUIID(java.lang.String) } * @param uiid * @return */ public ComponentSelector setUIID(String uiid) { for (Component c : this) { c.setUIID(uiid); } return this; } /** * Wrapper for {@link Component#remove() }. This will remove all of the components * in the current found set from their respective parents. * @return */ public ComponentSelector remove() { for (Component c : this) { c.remove(); } return this; } /** * Adds a focus listener to all components in found set. Wraps {@link Component#addFocusListener(com.codename1.ui.events.FocusListener) } * @param l * @return */ public ComponentSelector addFocusListener(FocusListener l) { for (Component c : this) { c.addFocusListener(l); } return this; } /** * Removes focus listener from all components in found set. Wraps {@link Component#removeFocusListener(com.codename1.ui.events.FocusListener) } * @param l * @return */ public ComponentSelector removeFocusListener(FocusListener l) { for (Component c : this) { c.removeFocusListener(l); } return this; } /** * Adds scroll listener to all components in found set. Wraps {@link Component#addScrollListener(com.codename1.ui.events.ScrollListener) } * @param l * @return */ public ComponentSelector addScrollListener(ScrollListener l) { for (Component c : this) { c.addScrollListener(l); } return this; } /** * Removes scroll listener from all components in found set. Wraps {@link Component#removeScrollListener(com.codename1.ui.events.ScrollListener) } * @param l * @return */ public ComponentSelector removeScrollListener(ScrollListener l) { for (Component c : this) { c.removeScrollListener(l); } return this; } /** * Sets select command text on all components in found set. Wraps {@link Component#setSelectCommandText(java.lang.String) } * @param text * @return */ public ComponentSelector setSelectCommandText(String text) { for (Component c : this) { c.setSelectCommandText(text); } return this; } /** * Wraps {@link Component#setLabelForComponent(com.codename1.ui.Label) } * @param l * @return */ public ComponentSelector setLabelForComponent(Label l) { for (Component c : this) { c.setLabelForComponent(l); } return this; } /** * Wraps {@link Component#paintBackgrounds(com.codename1.ui.Graphics) } * @param g * @return */ public ComponentSelector paintBackgrounds(Graphics g) { for (Component c : this) { c.paintBackgrounds(g); } return this; } /** * Wraps {@link Component#paintComponent(com.codename1.ui.Graphics) } * @param g * @return */ public ComponentSelector paintComponent(Graphics g) { for (Component c : this) { c.paintComponent(g); } return this; } /** * Wraps {@link Component#paint(com.codename1.ui.Graphics) } * @param g * @return */ public ComponentSelector paint(Graphics g) { for (Component c : this) { c.paint(g); } return this; } /** * Returns true if any of the components in the found set contains the provided coordinate. * Wraps {@link Component#contains(int, int) } * @param x * @param y * @return */ public boolean contains(int x, int y) { for (Component c : this) { if (c.contains(x, y)) { return true; } } return false; } /** * Sets all components in the found set focusability. * Wraps {@link Component#setFocusable(boolean) } * @param focus * @return */ public ComponentSelector setFocusable(boolean focus) { for (Component c : this) { c.setFocusable(focus); } return this; } /** * Wraps {@link Component#repaint() } * @return */ public ComponentSelector repaint() { for (Component c : this) { c.repaint(); } return this; } /** * Wraps {@link Component#repaint(int, int, int, int) } * @param x * @param y * @param w * @param h * @return */ public ComponentSelector repaint(int x, int y, int w, int h) { for (Component c : this) { c.repaint(x, y, w, h); } return this; } /** * Wraps {@link Component#setScrollAnimationSpeed(int) } * @param speed * @return */ public ComponentSelector setScrollAnimationSpeed(int speed) { for (Component c : this) { c.setScrollAnimationSpeed(speed); } return this; } /** * Wraps {@link Component#setSmoothScrolling(boolean) } * @param smooth * @return */ public ComponentSelector setSmoothScrolling(boolean smooth) { for (Component c : this) { c.setSmoothScrolling(smooth); } return this; } /** * Adds a drop listener to all components in found set. Wraps {@link Component#addDropListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector addDropListener(ActionListener l) { for (Component c : this) { c.addDropListener(l); } return this; } /** * Removes a drop listener from all components in found set. * Wraps {@link Component#removeDropListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector removeDropListener(ActionListener l) { for (Component c : this) { c.removeDropListener(l); } return this; } /** * Adds drag over listener to all components in found set. * Wraps {@link Component#addDragOverListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector addDragOverListener(ActionListener l) { for (Component c : this) { c.addDragOverListener(l); } return this; } /** * Removes drag over listener from all components in found set. * Wraps {@link Component#removeDragOverListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector removeDragOverListener(ActionListener l) { for (Component c : this) { c.removeDragOverListener(l); } return this; } /** * Adds pointer pressed listener to all components in found set. * Wraps {@link Component#addPointerPressedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector addPointerPressedListener(ActionListener l) { for (Component c : this) { c.addPointerPressedListener(l); } return this; } /** * Removes pointer pressed listener from all components in found set. * Wraps {@link Component#removePointerPressedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector removePointerPressedListener(ActionListener l) { for (Component c : this) { c.removePointerPressedListener(l); } return this; } /** * Adds pointer released listener to all components in found set. * Wraps {@link Component#addPointerReleasedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector addPointerReleasedListener(ActionListener l) { for (Component c : this) { c.addPointerReleasedListener(l); } return this; } /** * Removes pointer released listener from all components in found set. * Wraps {@link Component#removePointerReleasedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector removePointerReleasedListener(ActionListener l) { for (Component c : this) { c.removePointerReleasedListener(l); } return this; } /** * Adds pointer dragged listener to all components in found set. * Wraps {@link Component#addPointerDraggedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector addPointerDraggedListener(ActionListener l) { for (Component c : this) { c.addPointerDraggedListener(l); } return this; } /** * REmoves pointer dragged listener from all components in found set. * Wraps {@link Component#removePointerDraggedListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector removePointerDraggedListener(ActionListener l) { for (Component c : this) { c.removePointerDraggedListener(l); } return this; } /** * Sets pressed style of all components in found set. * Wraps {@link Component#setPressedStyle(com.codename1.ui.plaf.Style) } * @param style * @return */ public ComponentSelector setPressedStyle(Style style) { for (Component c : this) { c.setPressedStyle(style); } return this; } /** * Sets selected style of all components in found set. * Wraps {@link Component#setSelectedStyle(com.codename1.ui.plaf.Style) } * @param style * @return */ public ComponentSelector setSelectedStyle(Style style) { for (Component c : this) { c.setSelectedStyle(style); } return this; } /** * Sets disabled style of all components in found set. * Wraps {@link Component#setDisabledStyle(com.codename1.ui.plaf.Style) } * @param style * @return */ public ComponentSelector setDisabledStyle(Style style) { for (Component c : this) { c.setDisabledStyle(style); } return this; } /** * Sets unselected style of all components in found set. * Wraps {@link Component#setUnselectedStyle(com.codename1.ui.plaf.Style) } * @param style * @return */ public ComponentSelector setUnselectedStyle(Style style) { for (Component c : this) { c.setUnselectedStyle(style); } return this; } /** * Wraps {@link Component#requestFocus()} * @return */ public ComponentSelector requestFocus() { for (Component c : this) { c.requestFocus(); return this; } return this; } /** * Wraps {@link Component#refreshTheme()} * @return */ public ComponentSelector refreshTheme() { for (Component c : this) { c.refreshTheme(); } return this; } /** * Wraps {@link Component#refreshTheme(boolean) } * @param merge * @return */ public ComponentSelector refreshTheme(boolean merge) { for (Component c : this) { c.refreshTheme(merge); } return this; } /** * Wraps {@link Component#setCellRenderer(boolean) } * @param cell * @return */ public ComponentSelector setCellRenderer(boolean cell) { for (Component c : this) { c.setCellRenderer(cell); } return this; } /** * Wraps {@link Component#setScrollVisible(boolean) } * @param vis * @return */ public ComponentSelector setScrollVisible(boolean vis) { for (Component c : this) { c.setScrollVisible(vis); } return this; } /** * Wraps {@link Component#setEnabled(boolean) } * @param enabled * @return */ public ComponentSelector setEnabled(boolean enabled) { for (Component c : this) { c.setEnabled(enabled); } return this; } /** * Wraps {@link Component#setName(java.lang.String) } * @param name * @return */ public ComponentSelector setName(String name) { for (Component c : this) { c.setName(name); } return this; } /** * Wraps {@link Component#setRTL(boolean) } * @param rtl * @return */ public ComponentSelector setRTL(boolean rtl) { for (Component c : this) { c.setRTL(rtl); } return this; } /** * Wraps {@link Component#setTactileTouch(boolean) } * @param t * @return */ public ComponentSelector setTactileTouch(boolean t) { for (Component c : this) { c.setTactileTouch(t); } return this; } /** * Wraps {@link Component#setPropertyValue(java.lang.String, java.lang.Object) } * @param key * @param value * @return */ public ComponentSelector setPropertyValue(String key, Object value) { for (Component c : this) { c.setPropertyValue(key, value); } return this; } /** * Wraps {@link Component#paintLockRelease() } * @return */ public ComponentSelector paintLockRelease() { for (Component c : this) { c.paintLockRelease(); } return this; } /** * Wraps {@link Component#setSnapToGrid(boolean) } * @param s * @return */ public ComponentSelector setSnapToGrid(boolean s) { for (Component c : this) { c.setSnapToGrid(s); } return this; } public ComponentSelector setIgnorePointerEvents(boolean ignore) { for (Component c : this) { c.setIgnorePointerEvents(ignore); } return this; } public boolean isIgnorePointerEvents() { for (Component c : this) { return c.isIgnorePointerEvents(); } return false; } /** * Wraps {@link Component#setFlatten(boolean)} * @param f * @return */ public ComponentSelector setFlatten(boolean f) { for (Component c : this) { c.setFlatten(f); } return this; } /** * Wraps {@link Component#setTensileLength(int)} * @param len * @return */ public ComponentSelector setTensileLength(int len) { for (Component c : this) { c.setTensileLength(len); } return this; } /** * Wraps {@link Component#setGrabsPointerEvents(boolean) } * @param g * @return */ public ComponentSelector setGrabsPointerEvents(boolean g) { for (Component c : this) { c.setGrabsPointerEvents(g); } return this; } /** * Wraps {@link Component#setScrollOpacityChangeSpeed(int) } * @param scrollOpacityChangeSpeed * @return */ public ComponentSelector setScrollOpacityChangeSpeed(int scrollOpacityChangeSpeed) { for (Component c : this) { c.setScrollOpacityChangeSpeed(scrollOpacityChangeSpeed); } return this; } /** * Wraps {@link Component#growShrink(int) } * @param duration * @return */ public ComponentSelector growShrink(int duration) { for (Component c : this) { c.growShrink(duration); } return this; } /** * Wraps {@link Component#setDraggable(boolean) } * @param draggable * @return */ public ComponentSelector setDraggable(boolean draggable) { for (Component c : this) { c.setDraggable(draggable); } return this; } /** * Wraps {@link Component#setDropTarget(boolean) } * @param target * @return */ public ComponentSelector setDropTarget(boolean target) { for (Component c : this) { c.setDropTarget(target); } return this; } /** * Wraps {@link Component#setHideInPortrait(boolean) } * @param hide * @return */ public ComponentSelector setHideInPortait(boolean hide) { for (Component c : this) { c.setHideInPortrait(hide); } return this; } /** * Wraps {@link Component#setHidden(boolean,boolean) } * @param b * @param changeMargin * @return */ public ComponentSelector setHidden(boolean b, boolean changeMargin) { for (Component c : this) { c.setHidden(b, changeMargin); } return this; } /** * Wraps {@link Component#setHidden(boolean) } * @param b * @return */ public ComponentSelector setHidden(boolean b) { for (Component c : this) { c.setHidden(b); } return this; } /** * Wraps {@link Component#setComponentState(java.lang.Object) } * @param state * @return */ public ComponentSelector setComponentState(Object state) { for (Component c : this) { c.setComponentState(state); } return this; } /** * Wraps {@link Container#setLeadComponent(com.codename1.ui.Component) } * @param lead * @return */ public ComponentSelector setLeadComponent(Component lead) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.setLeadComponent(lead); } } return this; } /** * Wraps {@link Container#setLayout(com.codename1.ui.layouts.Layout) } * @param layout * @return */ public ComponentSelector setLayout(Layout layout) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.setLayout(layout); } } return this; } /** * Wraps {@link Container#invalidate() } * @return */ public ComponentSelector invalidate() { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.invalidate(); } } return this; } /** * Wraps {@link Container#setShouldCalcPreferredSize(boolean) } * @param shouldCalcPreferredSize * @return */ public ComponentSelector setShouldCalcPreferredSize(boolean shouldCalcPreferredSize) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.setShouldCalcPreferredSize(shouldCalcPreferredSize); } } return this; } /** * Wraps {@link Container#applyRTL(boolean) } * @param rtl * @return */ public ComponentSelector applyRTL(boolean rtl) { for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; cnt.applyRTL(rtl); } } return this; } /** * This removes all children from all containers in found set. Not to be confused with {@link #clear()}, which * removes components from the found set, but not from their respective parents. * Wraps {@link Container#removeAll() } * @return */ public ComponentSelector removeAll() { for (Component c : this) { if (c instanceof Container) { ((Container)c).removeAll(); } } return this; } /** * Wraps {@link Container#revalidate() } * @return */ public ComponentSelector revalidate() { for (Component c : this) { if (c instanceof Container) { ((Container)c).revalidate(); } } return this; } /** * Wraps {@link Container#forceRevalidate() } * @return */ public ComponentSelector forceRevalidate() { for (Component c : this) { if (c instanceof Container) { ((Container)c).forceRevalidate(); } } return this; } /** * Wraps {@link Container#layoutContainer() } * @return */ public ComponentSelector layoutContainer() { for (Component c : this) { if (c instanceof Container) { ((Container)c).layoutContainer(); } } return this; } /** * This returns a new ComponentSelector which includes a set of all results * of calling {@link Container#getComponentAt(int) } on containers in this * found set. This effectively allows us to get all of the ith elements of all * matched components. * @param index * @return New ComponentSelector with {@code index}th child of each container in the current found set. */ public ComponentSelector getComponentAt(int index) { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { if (c instanceof Container) { Container cnt = (Container)c; if (cnt.getComponentCount() > index) { out.add(cnt.getComponentAt(index)); } } } return new ComponentSelector(out); } /** * Returns true if any of the containers in the current found set contains * the provided component in its subtree. * Wraps {@link Container#contains(com.codename1.ui.Component) } * @param cmp * @return */ public boolean containsInSubtree(Component cmp) { for (Component c : this) { if (c instanceof Container) { if (((Container)c).contains(cmp)) { return true; } } } return false; } /** * Wraps {@link Container#scrollComponentToVisible(com.codename1.ui.Component) } * @param cmp * @return */ public ComponentSelector scrollComponentToVisible(Component cmp) { for (Component c : this) { if (c instanceof Container) { ((Container)c).scrollComponentToVisible(cmp); } } return this; } /** * Returns new ComponentSelector with the set of all components returned from calling * {@link Container#getComponentAt(int, int) } in the current found set. * @param x * @param y * @return New ComponentSelector with components at the given coordinates. */ public ComponentSelector getComponentAt(int x, int y) { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { if (c instanceof Container) { Component match = ((Container)c).getComponentAt(x, y); if (match != null) { out.add(match); } } } return new ComponentSelector(out); } /** * Wraps {@link Container#setScrollableX(boolean) } * @param b * @return */ public ComponentSelector setScrollableX(boolean b) { for (Component c : this) { if (c instanceof Container) { ((Container)c).setScrollableX(b); } } return this; } /** * Wraps {@link Container#setScrollableY(boolean) } * @param b * @return */ public ComponentSelector setScrollableY(boolean b) { for (Component c : this) { if (c instanceof Container) { ((Container)c).setScrollableY(b); } } return this; } /** * Wraps {@link Container#setScrollIncrement(int) } * @param b * @return */ public ComponentSelector setScrollIncrement(int b) { for (Component c : this) { if (c instanceof Container) { ((Container)c).setScrollIncrement(b); } } return this; } /** * Creates new ComponentSelector with the set of first focusable elements of * each of the containers in the current result set. * @return New component selector with first focusable element of each container in * current found set. * @see Container#findFirstFocusable() */ public ComponentSelector findFirstFocusable() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { if (c instanceof Container) { Component match = ((Container)c).findFirstFocusable(); if (match != null) { out.add(match); } } } return new ComponentSelector(out); } /** * Wraps {@link Container#animateHierarchyAndWait(int) }. * @param duration * @return */ public ComponentSelector animateHierarchyAndWait(int duration) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateHierarchy(duration)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return this; } /** * Animates the hierarchy of containers in this set. Wraps {@link Container#animateHierarchy(int) } * @param duration * @return */ public ComponentSelector animateHierarchy(int duration) { return animateHierarchy(duration, null); } /** * Wraps {@link Container#animateHierarchy(int) }. * @param duration * @param callback * @return */ public ComponentSelector animateHierarchy(int duration, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateHierarchy(duration)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Wraps {@link Container#animateHierarchyFadeAndWait(int,int) }. * @param duration * @param startingOpacity * @return */ public ComponentSelector animateHierarchyFadeAndWait(int duration, int startingOpacity) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateHierarchyFade(duration, startingOpacity)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return this; } /** * Wraps {@link Container#animateHierarchyAndWait(int) } * @param duration The duration of the animation. * @param startingOpacity The starting opacity. * @return Self for chaining. */ public ComponentSelector animateHierarchyFade(int duration, int startingOpacity) { return animateHierarchyFade(duration, startingOpacity, null); } /** * Wraps {@link Container#animateHierarchyFade(int,int) }. * @param duration * @param startingOpacity * @param callback * @return */ public ComponentSelector animateHierarchyFade(int duration, int startingOpacity, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateHierarchyFade(duration, startingOpacity)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Wraps {@link Container#animateLayoutFadeAndWait(int,int) }. * @param duration * @param startingOpacity * @return */ public ComponentSelector animateLayoutFadeAndWait(int duration, int startingOpacity) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateLayoutFade(duration, startingOpacity)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return this; } /** * Animates layout with fade on all containers in this set. Wraps {@link Container#animateLayoutFade(int, int) }. * @param duration * @param startingOpacity * @return Self for chaining. */ public ComponentSelector animateLayoutFade(int duration, int startingOpacity) { return animateLayoutFade(duration, startingOpacity, null); } /** * Wraps {@link Container#animateLayoutFade(int,int) }. * @param duration * @param startingOpacity * @param callback * @return */ public ComponentSelector animateLayoutFade(int duration, int startingOpacity, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateLayoutFade(duration, startingOpacity)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Wraps {@link Container#animateLayout(int) } * @param duration * @return */ public ComponentSelector animateLayout(int duration) { return animateLayout(duration, null); } /** * Wraps {@link Container#animateLayout(int) }. * @param duration * @param callback * @return */ public ComponentSelector animateLayout(int duration, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateLayout(duration)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Wraps {@link Container#animateLayoutAndWait(int) } * @param duration * @return */ public ComponentSelector animateLayoutAndWait(int duration) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateLayout(duration)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return this; } /** * Wraps {@link Container#animateUnlayout(int, int, java.lang.Runnable) * @param duration * @param opacity * @return */ public ComponentSelector animateUnlayout(int duration, int opacity) { return animateUnlayout(duration, opacity, null); } /** * Wraps {@link Container#animateUnlayout(int, int, java.lang.Runnable) } * @param duration * @param opacity * @param callback Callback to run when animation has completed. * @return */ public ComponentSelector animateUnlayout(int duration, int opacity, final SuccessCallback<ComponentSelector> callback) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateUnlayout(duration, opacity, null)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimation(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()])), new Runnable() { public void run() { if (callback != null) { callback.onSucess(ComponentSelector.this); } } }); } return this; } /** * Wraps {@link Container#animateUnlayoutAndWait(int, int) } * @param duration * @param opacity * @return */ public ComponentSelector animateUnlayoutAndWait(int duration, int opacity) { ArrayList<ComponentAnimation> animations = new ArrayList<ComponentAnimation>(); for (Component c : this) { if (c instanceof Container) { animations.add(((Container)c).createAnimateUnlayout(duration, opacity, null)); } } AnimationManager mgr = getAnimationManager(); if (animations.size() > 0 && mgr != null) { mgr.addAnimationAndBlock(ComponentAnimation.compoundAnimation(animations.toArray(new ComponentAnimation[animations.size()]))); } return this; } /** * Gets the AnimationManager for the components in this set. * * @return The AnimationManager for the components in this set. * @see Component#getAnimationManager() */ public AnimationManager getAnimationManager() { for (Component c : this) { AnimationManager mgr = c.getAnimationManager(); if (mgr != null) { return mgr; } } return null; } /** * Sets the text on all components in found set that support this. Currently this works with * Label, TextArea, SpanLabel, and SpanButtons, and subclasses thereof. * @param text The text to set in the componnet. * @return */ public ComponentSelector setText(String text) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setText(text); } else if (c instanceof TextArea) { ((TextArea)c).setText(text); } else if (c instanceof SpanLabel) { ((SpanLabel)c).setText(text); } else if (c instanceof SpanButton) { ((SpanButton)c).setText(text); } } return this; } /** * Gets the text on the first component in this set that supports this property. Currently this works with * Label, TextArea, SpanLabel, and SpanButtons, and subclasses thereof. * @return */ public String getText() { for (Component c : this) { if (c instanceof Label) { return ((Label)c).getText(); } else if (c instanceof TextArea) { return ((TextArea)c).getText(); } else if (c instanceof SpanLabel) { return ((SpanLabel)c).getText(); } else if (c instanceof SpanButton) { return ((SpanButton)c).getText(); } } return null; } /** * Sets the icon for components in found set. Only relevant to Labels, SpanLabels, and SpanButtons, and subclasses thereof. * @param icon * @return */ public ComponentSelector setIcon(Image icon) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setIcon(icon); } else if (c instanceof SpanLabel) { ((SpanLabel)c).setIcon(icon); } else if (c instanceof SpanButton) { ((SpanButton)c).setIcon(icon); } } return this; } /** * Sets the icons of all elements in this set to a material icon. * @param materialIcon Material icon charcode. * @param style The style for the icon. * @param size The size for the icon. (in mm) * @return Self for chaining. * @see FontImage#createMaterial(char, java.lang.String, float) */ public ComponentSelector setIcon(char materialIcon, Style style, float size) { FontImage img = FontImage.createMaterial(materialIcon, style, size); return setIcon(img); } /** * Sets the icon of all elements in this set to a material icon. This will use * the foreground color of each label as the icon's foreground color. * @param materialIcon The icon charcode. * @param size The size of the icon (in mm) * @return Self for chaining * @see FontImage#createMaterial(char, com.codename1.ui.plaf.Style, float) */ public ComponentSelector setIcon(char materialIcon, float size) { for (Component c : this) { if (c instanceof Label) { Label l = (Label)c; Style style = new Style(); Style cStyle = c.getUnselectedStyle(); style.setBgTransparency(0); style.setFgColor(cStyle.getFgColor()); l.setIcon(FontImage.createMaterial(materialIcon, style, size)); if (c instanceof Button) { Button b = (Button)c; style = new Style(); cStyle = c.getPressedStyle(); style.setBgTransparency(0); style.setFgColor(cStyle.getFgColor()); b.setPressedIcon(FontImage.createMaterial(materialIcon, style, size)); } } } return this; } /** * Sets the icon of all elements in this set to a material icon. This will use * the foreground color of the label. * @param materialIcon The material icon charcode. * @return Self for chaining. */ public ComponentSelector setIcon(char materialIcon) { for (Component c : this) { if (c instanceof Label) { Label l = (Label)c; Style style = new Style(); Style cStyle = c.getUnselectedStyle(); style.setBgTransparency(0); style.setFgColor(cStyle.getFgColor()); l.setIcon(FontImage.createMaterial(materialIcon, style, 3)); if (c instanceof Button) { Button b = (Button)c; style = new Style(); cStyle = c.getPressedStyle(); style.setBgTransparency(0); style.setFgColor(cStyle.getFgColor()); b.setPressedIcon(FontImage.createMaterial(materialIcon, style, 3)); } } } return this; } /** * Gets the set of all component forms from components in this set. * @return New ComponentSelector with forms all components in this set. */ public ComponentSelector getComponentForm() { HashSet<Component> out = new HashSet<Component>(); for (Component c : this) { out.add(c.getComponentForm()); } return new ComponentSelector(out); } /** * Sets vertical alignment of text. * @param valign * @return * @see Label#setVerticalAlignment(int) */ public ComponentSelector setVerticalAlignment(int valign) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setVerticalAlignment(valign); } } return this; } /** * Sets text position of text. Only relevant to labels. * @param pos * @return * @see Label#setTextPosition(int) */ public ComponentSelector setTextPosition(int pos) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setTextPosition(pos); } } return this; } /** * Sets gap. Only relevant to labels. * @param gap * @return * @see Label#setGap(int) * */ public ComponentSelector setGap(int gap) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setGap(gap); } } return this; } /** * Sets shift text. Only relevant to labels. * @param shift * @return * @see Label#setShiftText(int) */ public ComponentSelector setShiftText(int shift) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setShiftText(shift); } } return this; } /** * Wraps {@link Label#startTicker(long, boolean) } * @param delay * @param rightToLeft * @return */ public ComponentSelector startTicker(long delay, boolean rightToLeft) { for (Component c : this) { if (c instanceof Label) { ((Label)c).startTicker(delay, rightToLeft); } } return this; } /** * Wraps {@link Label#stopTicker() } * @return */ public ComponentSelector stopTicker() { for (Component c : this) { if (c instanceof Label) { ((Label)c).stopTicker(); } } return this; } /** * Wraps {@link Label#setTickerEnabled(boolean) } * @param b * @return */ public ComponentSelector setTickerEnabled(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setTickerEnabled(b); } } return this; } /** * Wraps {@link Label#setEndsWith3Points(boolean) } * @param b * @return */ public ComponentSelector setEndsWith3Points(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setEndsWith3Points(b); } } return this; } /** * Wraps {@link Label#setMask(java.lang.Object) } * @param mask * @return */ public ComponentSelector setMask(Object mask) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setMask(mask); } } return this; } /** * Wraps {@link Label#setMaskName(java.lang.String) } * @param name * @return */ public ComponentSelector setMaskName(String name) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setMaskName(name); } } return this; } /** * Wraps {@link Label#setShouldLocalize(boolean) } * @param b * @return */ public ComponentSelector setShouldLocalize(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setShouldLocalize(b); } } return this; } /** * Wraps {@link Label#setShiftMillimeters(int) } * @param b * @return */ public ComponentSelector setShiftMillimeters(int b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setShiftMillimeters(b); } } return this; } /** * Wraps {@link Label#setShowEvenIfBlank(boolean) } * @param b * @return */ public ComponentSelector setShowEvenIfBlank(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setShowEvenIfBlank(b); } } return this; } /** * Wraps {@link Label#setLegacyRenderer(boolean) } * @param b * @return */ public ComponentSelector setLegacyRenderer(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setLegacyRenderer(b); } } return this; } /** * Wraps {@link Label#setAutoSizeMode(boolean) } * @param b * @return */ public ComponentSelector setAutoSizeMode(boolean b) { for (Component c : this) { if (c instanceof Label) { ((Label)c).setAutoSizeMode(b); } } return this; } /** * Wraps {@link Button#setCommand(com.codename1.ui.Command) } * @param cmd * @return */ public ComponentSelector setCommand(Command cmd) { for (Component c : this) { if (c instanceof Button) { ((Button)c).setCommand(cmd); } } return this; } /** * Wraps {@link Button#setRolloverPressedIcon(com.codename1.ui.Image) } * @param icon * @return */ public ComponentSelector setRolloverPressedIcon(Image icon) { for (Component c : this) { if (c instanceof Button) { ((Button)c).setRolloverPressedIcon(icon); } } return this; } /** * Wraps {@link Button#setRolloverIcon(com.codename1.ui.Image) } * @param icon * @return */ public ComponentSelector setRolloverIcon(Image icon) { for (Component c : this) { if (c instanceof Button) { ((Button)c).setRolloverIcon(icon); } } return this; } /** * Wraps {@link Button#setPressedIcon(com.codename1.ui.Image) } * @param icon * @return */ public ComponentSelector setPressedIcon(Image icon) { for (Component c : this) { if (c instanceof Button) { ((Button)c).setPressedIcon(icon); } } return this; } /** * Wraps {@link Button#setDisabledIcon(com.codename1.ui.Image) } * @param icon * @return */ public ComponentSelector setDisabledIcon(Image icon) { for (Component c : this) { if (c instanceof Button) { ((Button)c).setDisabledIcon(icon); } } return this; } /** * Adds action listener to applicable components in found set. Currently this will apply to * Buttons, Lists, Sliders, TextAreas, OnOffSwitches, SpanButtons, and subclasses thereof. * @param l * @return */ public ComponentSelector addActionListener(ActionListener l) { for (Component c : this) { if (c instanceof Button) { ((Button)c).addActionListener(l); } else if (c instanceof com.codename1.ui.List) { ((com.codename1.ui.List)c).addActionListener(l); } else if (c instanceof Slider) { ((Slider)c).addActionListener(l); } else if (c instanceof TextArea) { ((TextArea)c).addActionListener(l); } else if (c instanceof OnOffSwitch) { ((OnOffSwitch)c).addActionListener(l); } else if (c instanceof SpanButton) { ((SpanButton)c).addActionListener(l); } } return this; } /** * Wraps {@link TextArea#setEditable(boolean) } * @param b * @return */ public ComponentSelector setEditable(boolean b) { for (Component c : this) { if (c instanceof TextArea) { ((TextArea)c).setEditable(b); } } return this; } /** * Wraps {@link TextField#addDataChangedListener(com.codename1.ui.events.DataChangedListener) } * @param l * @return */ public ComponentSelector addDataChangedListener(DataChangedListener l) { for (Component c : this) { if (c instanceof TextField) { ((TextField)c).addDataChangedListener(l); } } return this; } /** * Wraps {@link TextField#removeDataChangedListener(com.codename1.ui.events.DataChangedListener) } * @param l * @return */ public ComponentSelector removeDataChangedListener(DataChangedListener l) { for (Component c : this) { if (c instanceof TextField) { ((TextField)c).removeDataChangedListener(l); } } return this; } /** * Wraps {@link TextField#setDoneListener(com.codename1.ui.events.ActionListener) } * @param l * @return */ public ComponentSelector setDoneListener(ActionListener l) { for (Component c : this) { if (c instanceof TextField) { ((TextField)c).setDoneListener(l); } } return this; } // Now for the style stuff private static int dip2px(float dips) { return Display.getInstance().convertToPixels(dips); } /** * Sets padding to all sides of found set components in pixels. * @param padding Padding in pixels * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setPadding(int padding) { return setPadding(padding, padding, padding, padding); } /** * Sets padding to all components in found set. * @param top Top padding in pixels. * @param right Right padding in pixels * @param bottom Bottom padding in pixels. * @param left Left padding in pixels. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setPadding(int top, int right, int bottom, int left) { Style s = currentStyle(); s.setPaddingUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS); s.setPadding(top, bottom, left, right); return this; } /** * Sets padding to all components in found set in millimeters. * @param top Top padding in mm. * @param right Right padding in mm * @param bottom Bottom padding in mm. * @param left Left padding in mm. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setPaddingMillimeters(float top, float right, float bottom, float left) { return setPadding(dip2px(top), dip2px(right), dip2px(bottom), dip2px(left)); } /** * Sets padding in millimeters to all components in found set. * @param topBottom Top and bottom padding in mm. * @param leftRight Left and right padding in mm. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setPaddingMillimeters(float topBottom, float leftRight) { return setPaddingMillimeters(topBottom, leftRight, topBottom, leftRight); }; /** * Sets padding to all components in found set. * @param padding Padding applied to all sides in mm. * @return */ public ComponentSelector setPaddingMillimeters(float padding) { return setPaddingMillimeters(padding, padding); } /** * Sets padding on all components in found set. * @param topBottom Top and bottom padding in pixels. * @param leftRight Left and right padding in pixels. * @return */ public ComponentSelector setPadding(int topBottom, int leftRight) { return setPadding(topBottom, leftRight, topBottom, leftRight); } private int percentHeight(double percentage, Component parent) { return (int)Math.round((parent.getHeight() * percentage / 100)); } private int percentWidth(double percentage, Component parent) { return (int)Math.round((parent.getWidth() * percentage / 100)); } /** * Sets the padding on all components in found set as a percentage of their respective * parents' dimensions. Horizontal padding is set as a percentage of parent width. Vertical padding * is set as a percentage of parent height. * @param padding The padding expressed as a percent. * @return */ public ComponentSelector setPaddingPercent(double padding) { return setPaddingPercent(padding, padding, padding, padding); } /** * Sets padding on all components in found set as a percentage of their respective parents' dimensions. * @param topBottom Top and bottom padding as percentage of parent heights. * @param leftRight Left and right padding as percentage of parent widths. * @return */ public ComponentSelector setPaddingPercent(double topBottom, double leftRight) { return setPaddingPercent(topBottom, leftRight, topBottom, leftRight); } /** * Sets padding on all components in found set as a percentage of their respective parents' dimensions. * @param top Top padding as percentage of parent height. * @param right Right padding as percentage of parent width. * @param bottom Bottom padding as percentage of parent height. * @param left Left padding as percentage of parent width. * @return */ public ComponentSelector setPaddingPercent(double top, double right, double bottom, double left) { for (Component c : this) { Component parent = c.getParent(); if (parent != null) { // TODO : Change to currentStyle api... more complex with percents. Style s = getStyle(c); s.setPaddingUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS); s.setPadding( percentHeight(top, parent), percentHeight(bottom, parent), percentWidth(left, parent), percentWidth(right, parent) ); } } return this; } /** * Sets margin to all sides of found set components in pixels. * @param margin Margin in pixels * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setMargin(int margin) { return setMargin(margin, margin, margin, margin); } /** * Sets margin to all components in found set. * @param top Top margin in pixels. * @param right Right margin in pixels * @param bottom Bottom margin in pixels. * @param left Left margin in pixels. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setMargin(int top, int right, int bottom, int left) { Style s = currentStyle(); s.setMarginUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS); s.setMargin(top, bottom, left, right); return this; } /** * Sets margin on all components in found set. * @param topBottom Top and bottom margin in pixels. * @param leftRight Left and right margin in pixels. * @return */ public ComponentSelector setMargin(int topBottom, int leftRight) { return setMargin(topBottom, leftRight, topBottom, leftRight); } /** * Sets the margin on all components in found set as a percentage of their respective * parents' dimensions. Horizontal margin is set as a percentage of parent width. Vertical margin * is set as a percentage of parent height. * @param margin The margin expressed as a percent. * @return */ public ComponentSelector setMarginPercent(double margin) { return setMarginPercent(margin, margin, margin, margin); } /** * Sets margin on all components in found set as a percentage of their respective parents' dimensions. * @param topBottom Top and bottom margin as percentage of parent heights. * @param leftRight Left and right margin as percentage of parent widths. * @return */ public ComponentSelector setMarginPercent(double topBottom, double leftRight) { return setMarginPercent(topBottom, leftRight, topBottom, leftRight); } /** * Sets margin on all components in found set as a percentage of their respective parents' dimensions. * @param top Top margin as percentage of parent height. * @param right Right margin as percentage of parent width. * @param bottom Bottom margin as percentage of parent height. * @param left Left margin as percentage of parent width. * @return */ public ComponentSelector setMarginPercent(double top, double right, double bottom, double left) { for (Component c : this) { Component parent = c.getParent(); if (parent != null) { Style s = getStyle(c); s.setMarginUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS); s.setMargin( percentHeight(top, parent), percentHeight(bottom, parent), percentWidth(left, parent), percentWidth(right, parent) ); } } return this; } /** * Sets margin to all components in found set in millimeters. * @param top Top margin in mm. * @param right Right margin in mm * @param bottom Bottom margin in mm. * @param left Left margin in mm. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setMarginMillimeters(float top, float right, float bottom, float left) { return setMargin(dip2px(top), dip2px(right), dip2px(bottom), dip2px(left)); } /** * Sets margin in millimeters to all components in found set. * @param topBottom Top and bottom margin in mm. * @param leftRight Left and right margin in mm. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setMarginMillimeters(float topBottom, float leftRight) { return setMarginMillimeters(topBottom, leftRight, topBottom, leftRight); }; /** * Sets margin to all components in found set. * @param margin Margin applied to all sides in mm. * @return */ public ComponentSelector setMarginMillimeters(float margin) { return setMarginMillimeters(margin, margin); } /** * Creates a proxy style to mutate the styles of all component styles in found set. * @return * @see #getStyle(com.codename1.ui.Component) * @see Style#createProxyStyle(com.codename1.ui.plaf.Style...) */ public Style createProxyStyle() { HashSet<Style> styles = new HashSet<Style>(); for (Component c : this) { styles.add(getStyle(c)); } return Style.createProxyStyle(styles.toArray(new Style[styles.size()])); } /** * Merges style with all styles of components in current found set. * @param style * @return * @see Style#merge(com.codename1.ui.plaf.Style) * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector merge(Style style) { for (Component c : this) { getStyle(c).merge(style); } return this; } /** * Wraps {@link Style#setBgColor(int) } * @param bgColor * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBgColor(int bgColor) { currentStyle().setBgColor(bgColor); return this; } /** * Wraps {@link Style#setAlignment(int) } * @param alignment * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setAlignment(int alignment) { currentStyle().setAlignment(alignment); return this; } /** * Wraps {@link Style#setBgImage(com.codename1.ui.Image) } * @param bgImage * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBgImage(Image bgImage) { currentStyle().setBgImage(bgImage); return this; } /** * Wraps {@link Style#setBackgroundType(byte) } * @param backgroundType * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundType(byte backgroundType) { currentStyle().setBackgroundType(backgroundType); return this; } /** * Wraps {@link Style#setBackgroundGradientStartColor(int) } * @param startColor * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundGradientStartColor(int startColor) { currentStyle().setBackgroundGradientStartColor(startColor); return this; } /** * Wraps {@link Style#setBackgroundGradientEndColor(int) (int) } * @param endColor * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundGradientEndColor(int endColor) { currentStyle().setBackgroundGradientEndColor(endColor); return this; } /** * Wraps {@link Style#setBackgroundGradientRelativeX(float) } * @param x * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundGradientRelativeX(float x) { currentStyle().setBackgroundGradientRelativeX(x); return this; } /** * Wraps {@link Style#setBackgroundGradientRelativeY(float) } * @param y * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundGradientRelativeY(float y) { currentStyle().setBackgroundGradientRelativeY(y); return this; } /** * Wraps {@link Style#setBackgroundGradientRelativeSize(float) } * @param size * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBackgroundGradientRelativeSize(float size) { currentStyle().setBackgroundGradientRelativeSize(size); return this; } /** * Wraps {@link Style#setFgColor(int) } * @param color * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setFgColor(int color) { currentStyle().setFgColor(color); return this; } /** * Wraps {@link Style#setFont(com.codename1.ui.Font) } * @param f * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setFont(Font f) { currentStyle().setFont(f); return this; } /** * Wraps {@link Style#setUnderline(boolean) } * @param b * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setUnderline(boolean b) { currentStyle().setUnderline(b); return this; } /** * Wraps {@link Style#set3DText(boolean, boolean) } * @param t * @param raised * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector set3DText(boolean t, boolean raised) { currentStyle().set3DText(t, raised); return this; } /** * Wraps {@link Style#set3DTextNorth(boolean) } * @param north * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector set3DTextNorth(boolean north) { currentStyle().set3DTextNorth(north); return this; } /** * Wraps {@link Style#setOverline(boolean) } * @param b * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setOverline(boolean b) { currentStyle().setOverline(b); return this; } /** * Wraps {@link Style#setStrikeThru(boolean) } * @param b * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setStrikeThru(boolean b) { currentStyle().setStrikeThru(b); return this; } /** * Wraps {@link Style#setTextDecoration(int) } * @param textDecoration * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setTextDecoration(int textDecoration) { currentStyle().setTextDecoration(textDecoration); return this; } /** * Wraps {@link Style#setBgTransparency(byte) } * @param bgTransparency * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBgTransparency(int bgTransparency) { currentStyle().setBgTransparency(bgTransparency); return this; } /** * Wraps {@link Style#setOpacity(int) } * @param opacity * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setOpacity(int opacity) { currentStyle().setOpacity(opacity); return this; } /** * Wraps {@link Style#addStyleListener(com.codename1.ui.events.StyleListener) } * @param l * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector addStyleListener(StyleListener l) { currentStyle().addStyleListener(l); return this; } /** * Wraps {@link Style#removeStyleListener(com.codename1.ui.events.StyleListener) } * @param l * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector removeStyleListener(StyleListener l) { currentStyle().removeStyleListener(l); return this; } /** * Wraps {@link Style#removeListeners() } * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector removeStyleListeners() { currentStyle().removeListeners(); return this; } /** * Wraps {@link Style#setBorder(com.codename1.ui.plaf.Border) } * @param b * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBorder(Border b) { currentStyle().setBorder(b); return this; } /** * Wraps {@link Style#setBgPainter(com.codename1.ui.Painter) } * @param bgPainter * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setBgPainter(Painter bgPainter) { currentStyle().setBgPainter(bgPainter); return this; } private float getEffectiveFontSize(Component c) { Font f = c.getStyle().getFont(); while (f == null && c != null) { c = c.getParent(); if (c != null) { f = c.getStyle().getFont(); } } if (f != null) { return f.getPixelSize(); } return Font.getDefaultFont().getHeight() * 1.6f; } /** * Sets the font size of all components in found set. In pixels. * @param size Font size in pixels. * @return * @see #getStyle(com.codename1.ui.Component) */ public ComponentSelector setFontSize(float size) { for (Component c : this) { Style style = getStyle(c); Font curr = style.getFont(); if (curr == null || !curr.isTTFNativeFont()) { curr = c.getStyle().getFont(); } if (curr == null || !curr.isTTFNativeFont()) { Component parent = c.getParent(); while (parent != null && (curr == null || !curr.isTTFNativeFont())) { curr = parent.getStyle().getFont(); parent = parent.getParent(); } } if (curr == null || !curr.isTTFNativeFont()) { curr = Font.create("native:MainRegular"); } if (curr != null && curr.isTTFNativeFont()) { curr = curr.derive(size, 0); style.setFont(curr); } } return this; } public ComponentSelector setCursor(int cursor) { for (Component c : this) { c.setCursor(cursor); } return this; } /** * Sets the font size of all components in found set. In millimeters. * @param sizeMM Font size in mm. * @return */ public ComponentSelector setFontSizeMillimeters(float sizeMM) { return setFontSize(dip2px(sizeMM)); } /** * Sets the fonts size of all components in the found set as a percentage of the font * size of the components' respective parents. * @param sizePercentage Font size as a percentage of parent font size. * @return */ public ComponentSelector setFontSizePercent(double sizePercentage) { for (Component c : this) { Component parent = c.getParent(); if (parent != null) { float size = (float)(getEffectiveFontSize(parent) * sizePercentage / 100.0); Style style = getStyle(c); Font curr = style.getFont(); if (curr == null || !curr.isTTFNativeFont()) { curr = c.getStyle().getFont(); } if (curr == null || !curr.isTTFNativeFont()) { parent = c.getParent(); while (parent != null && (curr == null || !curr.isTTFNativeFont())) { curr = parent.getStyle().getFont(); parent = parent.getParent(); } } if (curr == null || !curr.isTTFNativeFont()) { curr = Font.create("native:MainRegular"); } if (curr != null && curr.isTTFNativeFont()) { curr = curr.derive(size, 0); style.setFont(curr); } } } return this; } }