blob: 3b7b59f61a9c938160a349e3572317a2875f27b1 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.ui.components;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.eclipse.core.databinding.observable.IObservableCollection;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.viewers.ITreeContentProvider;
public class DataAdapter<TItem> {
public static class ListAdapter<TItem> extends DataAdapter<TItem> {
final IObservableCollection<TItem> list;
public ListAdapter(final IObservableCollection<TItem> list, final IObservableValue<TItem> defaultValue) {
super(defaultValue);
if (list == null) {
throw new NullPointerException("list"); //$NON-NLS-1$
}
this.list= list;
}
@Override
public Object getAddParent(final Object element) {
return this.list;
}
@Override
public Object getParent(final Object element) {
return this.list;
}
@Override
protected Collection<? super TItem> getContainerFor(final Object element) {
return this.list;
}
@Override
public boolean isMoveAllowed(final Object element, final int direction) {
if (!super.isMoveAllowed(element, direction)) {
return false;
}
if (this.list instanceof List) {
final int oldIdx= ((List)this.list).indexOf(element);
final int newIdx= oldIdx + direction;
return (oldIdx >= 0 && newIdx >= 0 & newIdx < this.list.size());
}
return false;
}
@Override
public void delete(final List<? extends Object> elements) {
setDirty(true);
deleteDefault(elements);
this.list.removeAll(elements);
deleteChecked(elements);
}
@Override
public void move(final Object item, final int direction) {
final int oldIdx= ((IObservableList<TItem>)this.list).indexOf(item);
final int newIdx= oldIdx + direction;
if (oldIdx < 0 || newIdx < 0 || newIdx >= this.list.size()) {
return;
}
moveByIdx(oldIdx, newIdx);
}
protected void moveByIdx(final int oldIdx, final int newIdx) {
((IObservableList<TItem>)this.list).move(oldIdx, newIdx);
}
@Override
protected void changeDefault(final TItem oldItem, final TItem newItem) {
if (oldItem == null) {
if (this.defaultValue != null && this.list.isEmpty()) {
this.defaultValue.setValue(newItem);
}
return;
}
super.changeDefault(oldItem, newItem);
}
}
public static class TreeAdapter<TItem> extends DataAdapter<TItem> {
private final ITreeContentProvider contentProvider;
public TreeAdapter(final ITreeContentProvider contentProvider, final IObservableValue defaultValue) {
super(defaultValue);
if (contentProvider == null) {
throw new NullPointerException("contentProvider"); //$NON-NLS-1$
}
this.contentProvider= contentProvider;
}
@Override
public Object getAddParent(final Object element) {
if (isContentItem(element)) {
return getParent(element);
}
return element;
}
@Override
public Object getParent(final Object element) {
return this.contentProvider.getParent(element);
}
@Override
public Object[] getChildren(final Object element) {
return this.contentProvider.getChildren(element);
}
}
private Set<TItem> checkedSet;
protected final IObservableValue defaultValue;
private boolean isDirty;
public DataAdapter(final IObservableValue defaultValue) {
this.defaultValue= defaultValue;
}
public Object getAddParent(final Object element) {
return null;
}
public Object getParent(final Object element) {
return null;
}
public Object[] getChildren(final Object element) {
return null;
}
public boolean isAddAllowed(final Object element) {
return true;
}
public boolean isContentItem(final Object element) {
return true;
}
public boolean isModifyAllowed(final Object element) {
return isContentItem(element);
}
public boolean isMoveAllowed(final Object element, final int direction) {
return isModifyAllowed(element);
}
public boolean isDeleteAllowed(final Object element) {
return isModifyAllowed(element);
}
public TItem getModelItem(final Object element) {
return (TItem)element;
}
public Object getViewerElement(final TItem item, final Object parent) {
return item;
}
public void setCheckedModel(final Set<TItem> set) {
this.checkedSet= set;
}
protected Object getContainerFor(final Object element) {
return null;
}
protected IObservableValue getDefaultFor(final TItem item) {
return this.defaultValue;
}
public void setDefault(final TItem item) {
final IObservableValue observable= getDefaultFor(item);
if (observable == null) {
return;
}
this.isDirty= true;
if (item != null) {
observable.setValue(getDefaultValue(item));
}
}
public Object change(final TItem oldItem, final TItem newItem,
final Object parent, final Object container ) {
if (container instanceof Collection) {
final Collection<? super TItem> list= (Collection<? super TItem>) container;
setDirty(true);
changeDefault(oldItem, newItem);
if (oldItem == null) {
list.add(newItem);
}
else {
if (oldItem != newItem) { // can be directly manipulated or replaced)
if (list instanceof List) {
final int idx= ((List<? super TItem>) list).indexOf(oldItem);
((List<? super TItem>) list).set(idx, newItem);
}
else {
list.remove(oldItem);
list.add(newItem);
}
}
}
final Object editElement= getViewerElement(newItem, parent);
changeChecked(oldItem, newItem);
return editElement;
}
else {
throw new UnsupportedOperationException();
}
}
protected Object getDefaultValue(final TItem item) {
return item;
}
protected void changeDefault(final TItem oldItem, final TItem newItem) {
if (oldItem == null) {
return;
}
final IObservableValue observable= getDefaultFor(oldItem);
if (observable == null) {
return;
}
final Object oldValue= getDefaultValue(oldItem);
final Object newValue= getDefaultValue(newItem);
if (oldValue != newValue && oldValue.equals(observable.getValue())) {
observable.setValue(newValue);
}
}
protected void changeChecked(final TItem oldItem, final TItem newItem) {
if (this.checkedSet != null) {
if (oldItem == null) {
this.checkedSet.add(newItem);
}
else {
if (this.checkedSet.remove(oldItem)) {
this.checkedSet.add(newItem);
}
}
}
}
public void delete(final List<? extends Object> elements) {
setDirty(true);
deleteDefault(elements);
for (final Object element : elements) {
delete(getModelItem(element), getContainerFor(element));
}
deleteChecked(elements);
}
protected void delete(final TItem item, final Object container) {
if (container instanceof Collection) {
((Collection) container).remove(item);
}
else {
throw new UnsupportedOperationException();
}
}
protected void deleteDefault(final List<? extends Object> elements) {
if (elements.isEmpty()) {
return;
}
for (final Object element : elements) {
final TItem item= getModelItem(element);
if (item == null) {
continue;
}
final IObservableValue observable= getDefaultFor(item);
if (observable == null) {
continue;
}
final Object itemValue= getDefaultValue(item);
if (itemValue != null && itemValue.equals(observable.getValue())) {
observable.setValue(null);
return;
}
}
}
protected void deleteChecked(final List<? extends Object> elements) {
if (this.checkedSet != null) {
this.checkedSet.removeAll(elements);
}
}
public void move(final Object item, final int direction) {
throw new UnsupportedOperationException();
}
public void setDirty(final boolean isDirty) {
this.isDirty= isDirty;
}
public boolean isDirty() {
return this.isDirty;
}
}