Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,6 @@ private FormConstants() {
/** The resource type for date time input field v1 */
public static final String RT_FD_FORM_DATETIME_V1 = RT_FD_FORM_PREFIX + "datetime/v1/datetime";

/** The resource type for image choice v1 */
public static final String RT_FD_FORM_IMAGE_CHOICE_V1 = RT_FD_FORM_PREFIX + "imagechoice/v1/imagechoice";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright 2026 Adobe
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
package com.adobe.cq.forms.core.components.internal.models.v1.form;

import java.util.Map;

import javax.annotation.Nullable;
import javax.annotation.PostConstruct;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.jetbrains.annotations.NotNull;

import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.export.json.ExporterConstants;
import com.adobe.cq.forms.core.components.internal.form.FormConstants;
import com.adobe.cq.forms.core.components.internal.form.ReservedProperties;
import com.adobe.cq.forms.core.components.models.form.FieldType;
import com.adobe.cq.forms.core.components.models.form.ImageChoice;
import com.adobe.cq.forms.core.components.util.AbstractOptionsFieldImpl;
import com.fasterxml.jackson.annotation.JsonIgnore;

@Model(
adaptables = { SlingHttpServletRequest.class, Resource.class },
adapters = { ImageChoice.class,
ComponentExporter.class },
resourceType = { FormConstants.RT_FD_FORM_IMAGE_CHOICE_V1 })
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class ImageChoiceImpl extends AbstractOptionsFieldImpl implements ImageChoice {

private static final String PN_SELECTION_TYPE = "selectionType";

@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_ORIENTATION)
@Nullable
protected String orientationJcr;

@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = PN_SELECTION_TYPE)
@Nullable
protected String selectionTypeJcr;

@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_IMAGE_SRC)
@Nullable
protected String[] imageSrcArray;

private Orientation orientation;
private SelectionType selectionType;

@PostConstruct
private void initImageChoiceModel() {
orientation = Orientation.fromString(orientationJcr);
selectionType = SelectionType.fromString(selectionTypeJcr);
}

@Override
public @NotNull Map<String, Object> getCustomLayoutProperties() {
Map<String, Object> customLayoutProperties = super.getCustomLayoutProperties();
if (orientation != null) {
customLayoutProperties.put(ReservedProperties.PN_ORIENTATION, orientation.getValue());
}
if (selectionType != null) {
customLayoutProperties.put(PN_SELECTION_TYPE, selectionType.getValue());
}
return customLayoutProperties;
}

@Override
@JsonIgnore
public Orientation getOrientation() {
return orientation;
}

@Override
@JsonIgnore
public SelectionType getSelectionType() {
return selectionType;
}

@Override
public String[] getImageSrc() {
return imageSrcArray != null ? imageSrcArray.clone() : null;
}

@Override
public Integer getMinItems() {
return minItems;
}

@Override
public Integer getMaxItems() {
return maxItems;
}

@Override
public String getFieldType() {
if (selectionType == SelectionType.MULTI) {
return FieldType.CHECKBOX_GROUP.getValue();
}
return FieldType.RADIO_GROUP.getValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright 2026 Adobe
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
package com.adobe.cq.forms.core.components.models.form;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.osgi.annotation.versioning.ConsumerType;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Defines the form {@code ImageChoice} Sling Model used for the
* {@code /apps/core/fd/components/form/imagechoice/v1/imagechoice} component.
*
* <p>
* The ImageChoice component allows users to select one or more options
* represented by images. It supports both single-select (radio button behavior)
* and multi-select (checkbox group behavior) modes.
* </p>
*
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
@ConsumerType
public interface ImageChoice extends Field, OptionsConstraint, ContainerConstraint {

/**
* Defines the selection type for image choice.
* Possible values: {@code single}, {@code multi}
*
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
enum SelectionType {
SINGLE("single"),
MULTI("multi");

private String value;

SelectionType(String value) {
this.value = value;
}

public static SelectionType fromString(String value) {
for (SelectionType type : SelectionType.values()) {
if (StringUtils.equals(value, type.value)) {
return type;
}
}
return SINGLE;
}

public String getValue() {
return value;
}

@Override
@JsonValue
public String toString() {
return value;
}
}

/**
* Defines the orientation for image choice layout.
* Possible values: {@code horizontal}, {@code vertical}
*
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
enum Orientation {
HORIZONTAL("horizontal"),
VERTICAL("vertical");

private String value;

Orientation(String value) {
this.value = value;
}

public static Orientation fromString(String value) {
for (Orientation type : Orientation.values()) {
if (StringUtils.equals(value, type.value)) {
return type;
}
}
return HORIZONTAL;
}

public String getValue() {
return value;
}

@Override
@JsonValue
public String toString() {
return value;
}
}

/**
* Returns the orientation of the image choice component.
*
* @return {@link Orientation}
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
@JsonIgnore
default Orientation getOrientation() {
return Orientation.HORIZONTAL;
}

/**
* Returns the selection type of the image choice component.
* {@code single} behaves like radio buttons (one selection),
* {@code multi} behaves like checkbox group (multiple selections).
*
* @return {@link SelectionType}
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
@JsonIgnore
default SelectionType getSelectionType() {
return SelectionType.SINGLE;
}

/**
* Returns the array of image source paths corresponding to each enum option.
* The array is parallel to the enums array - imageSrc[i] is the image for enum[i].
*
* @return array of image source paths, or null if not set
* @since com.adobe.cq.forms.core.components.models.form 5.13.0
*/
@Nullable
String[] getImageSrc();
}
Loading
Loading