diff --git a/.gitignore b/.gitignore index ebc6e53..4a36175 100644 --- a/.gitignore +++ b/.gitignore @@ -172,4 +172,5 @@ dmypy.json .pytype/ # Cython debug symbols -cython_debug/ \ No newline at end of file +cython_debug/ +.worktrees/ \ No newline at end of file diff --git a/src/com/yusufcihan/DynamicComponents/DynamicComponents.java b/src/com/yusufcihan/DynamicComponents/DynamicComponents.java index d107347..5899b00 100644 --- a/src/com/yusufcihan/DynamicComponents/DynamicComponents.java +++ b/src/com/yusufcihan/DynamicComponents/DynamicComponents.java @@ -62,6 +62,9 @@ public class DynamicComponents extends AndroidNonvisibleComponent { // IDs of components created with Dynamic Components private final HashMap COMPONENT_IDS = new HashMap<>(); + // Tags associated with components + private final HashMap> COMPONENT_TAGS = new HashMap<>(); + private Object lastUsedId = ""; private final ArrayList componentListeners = new ArrayList<>(); @@ -188,6 +191,32 @@ public void run() { } } + @SimpleFunction(description = + "Creates a new dynamic component synchronously in the given container (arrangement/canvas), " + + "registers it internally, and returns the component object directly. " + + "If the ID is empty, a unique ID will be automatically generated." + ) + public Component CreateSync(final AndroidViewComponent in, Object componentName, String id) throws Exception { + String actualId = id; + if (actualId == null || actualId.trim().isEmpty()) { + actualId = GenerateID(); + } + + if (!COMPONENTS.containsKey(actualId)) { + lastUsedId = actualId; + Class mClass = Class.forName(Utils.getClassName(componentName)); + final Constructor mConstructor = mClass.getConstructor(ComponentContainer.class); + Component mComponent = Utils.createInstance(mConstructor, in); + COMPONENT_IDS.put(mComponent, actualId); + COMPONENTS.put(actualId, mComponent); + notifyListenersOfCreation(mComponent, actualId); + ComponentBuilt(mComponent, actualId, mComponent.getClass().getSimpleName()); + return mComponent; + } else { + throw new YailRuntimeError("All component IDs must be unique, the component ID '" + actualId + "' has already used before.", TAG); + } + } + @SimpleFunction(description = "Creates a new dynamic component in given container (arrangement/canvas) and return it without saving it to the " + "created components list, so it won't be attached to an ID. Note that you can't create components " + @@ -321,11 +350,11 @@ public void Move(AndroidViewComponent arrangement, AndroidViewComponent componen "so its ID can be reused for other components that are going to be created later." ) public void Remove(String id) { - Object component = COMPONENTS.get(id); + Component component = COMPONENTS.get(id); if (component == null) { return; } - RemoveComponent((AndroidViewComponent)component); + RemoveComponent(component); COMPONENTS.remove(id); COMPONENT_IDS.remove(component); } @@ -335,24 +364,28 @@ public void Remove(String id) { "But if the given component is dynamically created by this extension, this block will also " + "de-register its ID so its ID can be reused for other components that are going to be created later." ) - public void RemoveComponent(AndroidViewComponent component) { + public void RemoveComponent(Component component) { try { Method mMethod = Utils.getMethod(component, "getView"); if (mMethod != null) { final View mComponent = (View) mMethod.invoke(component); - final ViewGroup mParent = (ViewGroup) mComponent.getParent(); - if (postOnUiThread) { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { + if (mComponent != null) { + final ViewGroup mParent = (ViewGroup) mComponent.getParent(); + if (mParent != null) { + if (postOnUiThread) { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + mParent.removeView(mComponent); + } + }); + } else { mParent.removeView(mComponent); } - }); - } else { - mParent.removeView(mComponent); + } } } - final String[] closeMethods = new String[] { "onPause", "onDestroy" }; + final String[] closeMethods = new String[] { "onPause", "onDestroy", "onDelete" }; for (String methodName : closeMethods) { final Method invokeMethod = Utils.getMethod(component, methodName); if (invokeMethod != null) @@ -365,6 +398,7 @@ public void run() { COMPONENTS.remove(storedComponentId); COMPONENT_IDS.remove(component); } + COMPONENT_TAGS.remove(component); } catch (Exception e) { e.printStackTrace(); } @@ -468,6 +502,70 @@ public YailList UsedIDs() { return YailList.makeList(COMPONENTS.keySet()); } + @SimpleFunction(description = "Adds a custom text tag to the specified component.") + public void AddTag(Component component, String tag) { + if (component == null || tag == null || tag.trim().isEmpty()) { + return; + } + ArrayList tags = COMPONENT_TAGS.get(component); + if (tags == null) { + tags = new ArrayList<>(); + COMPONENT_TAGS.put(component, tags); + } + if (!tags.contains(tag)) { + tags.add(tag); + } + } + + @SimpleFunction(description = "Removes a custom text tag from the specified component.") + public void RemoveTag(Component component, String tag) { + if (component == null || tag == null) { + return; + } + ArrayList tags = COMPONENT_TAGS.get(component); + if (tags != null) { + tags.remove(tag); + if (tags.isEmpty()) { + COMPONENT_TAGS.remove(component); + } + } + } + + @SimpleFunction(description = "Returns true if the specified component has the given tag.") + public boolean HasTag(Component component, String tag) { + if (component == null || tag == null) { + return false; + } + ArrayList tags = COMPONENT_TAGS.get(component); + return tags != null && tags.contains(tag); + } + + @SimpleFunction(description = "Returns a list of all tags associated with the specified component.") + public YailList GetTags(Component component) { + if (component == null) { + return YailList.makeEmptyList(); + } + ArrayList tags = COMPONENT_TAGS.get(component); + if (tags == null) { + return YailList.makeEmptyList(); + } + return YailList.makeList(tags); + } + + @SimpleFunction(description = "Returns a list of all components that have the specified tag.") + public YailList GetComponentsByTag(String tag) { + if (tag == null) { + return YailList.makeEmptyList(); + } + ArrayList matched = new ArrayList<>(); + for (Map.Entry> entry : COMPONENT_TAGS.entrySet()) { + if (entry.getValue().contains(tag)) { + matched.add(entry.getKey()); + } + } + return YailList.makeList(matched); + } + @SimpleProperty(description = "Returns the version of this extension.") public int Version() { return DynamicComponents.class.getAnnotation(DesignerComponent.class).version();