use of io.jmix.ui.component.data.HasValueSource in project jmix by jmix-framework.
the class EditorBuilderProcessor method initEntity.
@Nullable
protected <E> E initEntity(EditorBuilder<E> builder, @Nullable CollectionContainer<E> container) {
E entity;
boolean oneToOneComposition = false;
EntityValueSource entityValueSource = null;
HasValue<E> field = builder.getField();
if (field instanceof HasValueSource) {
ValueSource valueSource = ((HasValueSource) field).getValueSource();
if (valueSource instanceof EntityValueSource) {
entityValueSource = (EntityValueSource) valueSource;
oneToOneComposition = isCompositionProperty(entityValueSource);
}
}
if (builder.getMode() == EditMode.CREATE || (oneToOneComposition && field.getValue() == null)) {
if (builder.getNewEntity() == null) {
entity = metadata.create(builder.getEntityClass());
} else {
entity = builder.getNewEntity();
}
if (container instanceof Nested) {
initializeNestedEntity(entity, (Nested) container);
}
if (oneToOneComposition) {
Object ownerEntity = entityValueSource.getItem();
MetaProperty inverseProp = entityValueSource.getMetaPropertyPath().getMetaProperty().getInverse();
if (inverseProp != null) {
EntityValues.setValue(entity, inverseProp.getName(), ownerEntity);
}
}
if (builder.getInitializer() != null) {
builder.getInitializer().accept(entity);
}
} else {
entity = builder.getEditedEntity();
}
return entity;
}
use of io.jmix.ui.component.data.HasValueSource in project jmix by jmix-framework.
the class LookupBuilderProcessor method getFetchPlanForField.
/**
* The method evaluates the fetch plan that is used for the entity in the given {@code field}
* <p>
* If the value for a component (e.g. {@link EntityPicker}) is selected from lookup screen then there may be cases
* when in entities in lookup screen some attributes required in the editor are not loaded.
*
* @return a view or {@code null} if the fetch plan cannot be evaluated
*/
@Nullable
protected FetchPlan getFetchPlanForField(HasValue field) {
if (field instanceof HasValueSource) {
ValueSource valueSource = ((HasValueSource) field).getValueSource();
if (valueSource instanceof ContainerValueSource) {
ContainerValueSource containerValueSource = (ContainerValueSource) valueSource;
InstanceContainer container = containerValueSource.getContainer();
FetchPlan fetchPlan = container.getFetchPlan();
if (fetchPlan != null) {
MetaPropertyPath metaPropertyPath = containerValueSource.getMetaPropertyPath();
FetchPlan curFetchPlan = fetchPlan;
for (MetaProperty metaProperty : metaPropertyPath.getMetaProperties()) {
FetchPlanProperty viewProperty = curFetchPlan.getProperty(metaProperty.getName());
if (viewProperty != null) {
curFetchPlan = viewProperty.getFetchPlan();
}
if (curFetchPlan == null)
break;
}
if (curFetchPlan != fetchPlan) {
return curFetchPlan;
}
}
}
}
return null;
}
use of io.jmix.ui.component.data.HasValueSource in project jmix by jmix-framework.
the class AbstractTable method addGeneratedColumn.
@Override
public void addGeneratedColumn(String columnId, ColumnGenerator<? super E> generator) {
checkNotNullArgument(columnId, "columnId is null");
checkNotNullArgument(generator, "generator is null for column id '%s'", columnId);
EntityTableItems<E> entityTableSource = (EntityTableItems<E>) getItems();
MetaPropertyPath targetCol = entityTableSource != null ? entityTableSource.getEntityMetaClass().getPropertyPath(columnId) : null;
Object generatedColumnId = targetCol != null ? targetCol : columnId;
Column column = getColumn(columnId);
Column associatedRuntimeColumn = null;
if (column == null) {
Column<E> newColumn = createColumn(generatedColumnId, this);
columns.put(newColumn.getId(), newColumn);
columnsOrder.add(newColumn);
associatedRuntimeColumn = newColumn;
}
// save column order
Object[] visibleColumns = component.getVisibleColumns();
boolean removeOldGeneratedColumn = component.getColumnGenerator(generatedColumnId) != null;
// replace generator for column if exist
if (removeOldGeneratedColumn) {
component.removeGeneratedColumn(generatedColumnId);
}
component.addGeneratedColumn(generatedColumnId, new CustomColumnGenerator(generator, associatedRuntimeColumn) {
@Nullable
@Override
public Object generateCell(com.vaadin.v7.ui.Table source, Object itemId, Object columnId) {
EntityTableItems<E> entityTableSource = (EntityTableItems<E>) getItems();
if (entityTableSource == null) {
return null;
}
E entity = entityTableSource.getItem(itemId);
io.jmix.ui.component.Component component = getColumnGenerator().generateCell(entity);
if (component == null) {
return null;
}
if (component instanceof PlainTextCell) {
return ((PlainTextCell) component).getText();
}
if (component instanceof BelongToFrame) {
BelongToFrame belongToFrame = (BelongToFrame) component;
if (belongToFrame.getFrame() == null) {
belongToFrame.setFrame(getFrame());
}
}
component.setParent(AbstractTable.this);
AbstractComponent vComponent = component.unwrapComposition(AbstractComponent.class);
if (component instanceof HasValueSource) {
HasValueSource<?> hasValueSource = (HasValueSource) component;
vComponent.setData(hasValueSource);
}
// wrap field for show required asterisk
if ((vComponent instanceof com.vaadin.v7.ui.Field) && (((com.vaadin.v7.ui.Field) vComponent).isRequired())) {
VerticalLayout layout = new VerticalLayout();
layout.setMargin(false);
layout.setSpacing(false);
layout.addComponent(vComponent);
if (vComponent.getWidth() < 0) {
layout.setWidthUndefined();
}
layout.addComponent(vComponent);
vComponent = layout;
}
return vComponent;
}
});
if (removeOldGeneratedColumn) {
// restore column order
component.setVisibleColumns(visibleColumns);
}
}
use of io.jmix.ui.component.data.HasValueSource in project jmix by jmix-framework.
the class AttributeRecalculationListener method accept.
@Override
public void accept(HasValue.ValueChangeEvent valueChangeEvent) {
if (Boolean.TRUE.equals(recalculationInProgress.get())) {
return;
}
try {
recalculationInProgress.set(true);
Component component = valueChangeEvent.getComponent();
if (component instanceof HasValueSource && ((HasValueSource<?>) component).getValueSource() instanceof ContainerValueSource) {
ContainerValueSource<?, ?> valueSource = (ContainerValueSource<?, ?>) ((HasValueSource<?>) component).getValueSource();
InstanceContainer<?> container = valueSource.getContainer();
Object entity = container.getItem();
EntityValues.setValue(entity, DynAttrUtils.getPropertyFromAttributeCode(attribute.getCode()), valueChangeEvent.getValue());
recalculationManager.recalculateByAttribute(entity, attribute);
}
} finally {
recalculationInProgress.remove();
}
}
use of io.jmix.ui.component.data.HasValueSource in project jmix by jmix-framework.
the class EditorBuilderProcessor method buildEditor.
@SuppressWarnings("unchecked")
public <E, S extends Screen> S buildEditor(EditorBuilder<E> builder) {
FrameOwner origin = builder.getOrigin();
Screens screens = getScreenContext(origin).getScreens();
ListComponent<E> listComponent = builder.getListComponent();
CollectionContainer<E> container = builder.getContainer();
if (container == null && listComponent != null) {
DataUnit items = listComponent.getItems();
container = items instanceof ContainerDataUnit ? ((ContainerDataUnit) items).getContainer() : null;
}
E entity = initEntity(builder, container);
if (builder.getMode() == EditMode.EDIT && entity == null) {
throw new IllegalStateException(String.format("Editor of %s cannot be open with mode EDIT, entity is not set", builder.getEntityClass()));
}
Screen screen = createScreen(builder, screens, entity);
EditorScreen<E> editorScreen = (EditorScreen<E>) screen;
editorScreen.setEntityToEdit(entity);
DataContext parentDataContext = setupParentDataContext(origin, screen, container, builder.getParentDataContext());
if (container != null) {
CollectionContainer<E> ct = container;
screen.addAfterCloseListener(event -> {
CloseAction closeAction = event.getCloseAction();
if (isCommitCloseAction(closeAction)) {
E entityFromEditor = getCommittedEntity(editorScreen, parentDataContext);
E reloadedEntity = transformForCollectionContainer(entityFromEditor, ct);
E committedEntity = transform(reloadedEntity, builder);
E mergedEntity = merge(committedEntity, origin, parentDataContext);
if (builder.getMode() == EditMode.CREATE) {
boolean addsFirst;
if (!(ct instanceof Nested)) {
addsFirst = screenProperties.isCreateActionAddsFirst();
if (builder.getAddFirst() != null) {
addsFirst = builder.getAddFirst();
}
} else {
addsFirst = false;
}
if (ct instanceof Nested || !addsFirst) {
ct.getMutableItems().add(mergedEntity);
} else {
ct.getMutableItems().add(0, mergedEntity);
}
} else {
ct.replaceItem(mergedEntity);
}
}
if (listComponent instanceof io.jmix.ui.component.Component.Focusable) {
((io.jmix.ui.component.Component.Focusable) listComponent).focus();
}
});
}
HasValue<E> field = builder.getField();
if (field != null) {
if (parentDataContext == null && field instanceof HasValueSource) {
ValueSource fieldValueSource = ((HasValueSource) field).getValueSource();
if (fieldValueSource instanceof EntityValueSource) {
if (isCompositionProperty((EntityValueSource) fieldValueSource)) {
DataContext thisDataContext = UiControllerUtils.getScreenData(origin).getDataContext();
DataContext dataContext = UiControllerUtils.getScreenData(screen).getDataContext();
checkDataContext(screen, dataContext);
dataContext.setParent(thisDataContext);
}
}
}
screen.addAfterCloseListener(event -> {
CloseAction closeAction = event.getCloseAction();
if (isCommitCloseAction(closeAction)) {
E entityFromEditor = editorScreen.getEditedEntity();
E reloadedEntity = transformForField(entityFromEditor, field);
E editedEntity = transform(reloadedEntity, builder);
if (field instanceof EntityComboBox) {
EntityComboBox entityComboBox = ((EntityComboBox) field);
Options options = entityComboBox.getOptions();
if (options instanceof EntityOptions) {
EntityOptions entityOptions = (EntityOptions) options;
if (entityOptions.containsItem(editedEntity)) {
entityOptions.updateItem(editedEntity);
}
}
}
if (field instanceof SupportsUserAction) {
((SupportsUserAction) field).setValueFromUser(editedEntity);
} else {
field.setValue(editedEntity);
}
}
if (field instanceof io.jmix.ui.component.Component.Focusable) {
((io.jmix.ui.component.Component.Focusable) field).focus();
}
});
}
if (builder instanceof EditorClassBuilder) {
Consumer<AfterScreenShowEvent> afterShowListener = ((EditorClassBuilder) builder).getAfterShowListener();
if (afterShowListener != null) {
screen.addAfterShowListener(new AfterShowListenerAdapter(afterShowListener));
}
Consumer<AfterScreenCloseEvent> closeListener = ((EditorClassBuilder) builder).getAfterCloseListener();
if (closeListener != null) {
screen.addAfterCloseListener(new AfterCloseListenerAdapter(closeListener));
}
}
return (S) screen;
}
Aggregations