io.devbench.uibuilder.components.masterdetail.connector.GridMasterConnector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of uibuilder-master-detail-controller Show documentation
Show all versions of uibuilder-master-detail-controller Show documentation
A Master-Detail Controller component for the UIBuilder Framework
/*
*
* Copyright © 2018 Webvalto Ltd.
*
* 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 io.devbench.uibuilder.components.masterdetail.connector;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridSelectionModel;
import com.vaadin.flow.data.provider.DataCommunicator;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.shared.Registration;
import io.devbench.uibuilder.api.components.masterconnector.AbstractUIBuilderMasterConnector;
import io.devbench.uibuilder.api.exceptions.ComponentInternalException;
import io.devbench.uibuilder.api.exceptions.MasterConnectorNotDirectlyModifiableException;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
@Slf4j
public class GridMasterConnector extends AbstractUIBuilderMasterConnector, T> {
private static final Field DATA_COMMUNICATOR_RESEND_ENTIRE_RANGE_FIELD;
static {
Field resendEntireRange = null;
try {
resendEntireRange = DataCommunicator.class.getDeclaredField("resendEntireRange");
resendEntireRange.setAccessible(true);
} catch (NoSuchFieldException e) {
log.error("Could not get resendEntireRange field from DataCommunicator class", e);
}
DATA_COMMUNICATOR_RESEND_ENTIRE_RANGE_FIELD = resendEntireRange;
}
private Registration gridSelectionListenerRegistration;
private Collection selectedItems = Collections.emptyList();
@SuppressWarnings("unchecked")
public GridMasterConnector() {
super((Class) Grid.class);
}
@Override
public void onConnect(@NotNull Grid masterComponent) {
super.onConnect(masterComponent);
gridSelectionListenerRegistration = getMasterComponent().addSelectionListener(event -> {
Collection previouslySelectedItems = getSelectedItems();
Collection newlySelectedItems = event.getAllSelectedItems();
this.selectedItems = newlySelectedItems;
fireSelectionChangedEvent(
new MasterSelectionChangedEvent<>(event.getSource(), event.isFromClient(), previouslySelectedItems, newlySelectedItems));
});
}
@Override
public void disconnect() {
if (gridSelectionListenerRegistration != null) {
gridSelectionListenerRegistration.remove();
gridSelectionListenerRegistration = null;
}
}
@Override
public Collection getSelectedItems() {
return selectedItems;
}
@Override
public void setSelectedItems(@NotNull Collection items) {
Objects.requireNonNull(items, "Selected items collection cannot be null");
Collection previouslySelectedItems = getSelectedItems();
GridSelectionModel selectionModel = getMasterComponent().getSelectionModel();
previouslySelectedItems.stream()
.filter(item -> !items.contains(item))
.forEach(selectionModel::deselect);
items.stream()
.filter(item -> !previouslySelectedItems.contains(item))
.forEach(selectionModel::select);
selectedItems = Collections.unmodifiableCollection(items);
}
@Override
public void refresh() {
getMasterComponent().getDataProvider().refreshAll();
}
@Override
public void refresh(T item) {
getMasterComponent().getDataProvider().refreshItem(item);
}
@Override
public void setEnabled(boolean enabled) {
getMasterComponent().setEnabled(enabled);
}
@Override
public boolean isEnabled() {
return getMasterComponent().isEnabled();
}
@Override
public boolean isDirectModifiable() {
return getListDataProvider().isPresent();
}
@Override
public void addItem(T item) {
ListDataProvider listDataProvider = getListDataProvider().orElseThrow(MasterConnectorNotDirectlyModifiableException::new);
listDataProvider.getItems().add(item);
}
@Override
public void removeItem(T item) {
ListDataProvider listDataProvider = getListDataProvider().orElseThrow(MasterConnectorNotDirectlyModifiableException::new);
listDataProvider.getItems().remove(item);
}
private Optional> getListDataProvider() {
Grid masterComponent = getMasterComponent();
if (masterComponent.getDataProvider() instanceof ListDataProvider) {
@SuppressWarnings("unchecked")
ListDataProvider listDataProvider = (ListDataProvider) masterComponent.getDataProvider();
return Optional.of(listDataProvider);
}
return Optional.empty();
}
public void applyCustomFix() {
try {
DATA_COMMUNICATOR_RESEND_ENTIRE_RANGE_FIELD.set(getMasterComponent().getDataCommunicator(), false);
} catch (IllegalAccessException e) {
throw new ComponentInternalException("Could not set DataCommunicator's resendEntireRange field value to false", e);
}
}
@Override
public int getPriority() {
return DEFAULT_PRIORITY - 500;
}
}