/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.ui.util;
import java.util.List;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.ui.editparts.EntityPartEvent;
import org.whole.lang.ui.editparts.ITextualEntityPart;
import org.whole.lang.ui.editparts.IdentityEntityPartListener;
import org.whole.lang.ui.editparts.ModelObserver;
import org.whole.lang.ui.viewers.IEntityPartViewer;
/**
* @author Enrico Persiani
*/
public class CaretUpdater extends IdentityEntityPartListener {
public static final CaretUpdater NULL_UPDATER = new CaretUpdater() {
public void sheduleAsyncUpdate() {
}
public void sheduleSyncUpdate() {
}
};
private EditPartViewer viewer;
private IEntity selectedEntity;
private int start;
private int end;
private Point location;
private boolean deselectAll = true;
private CaretUpdater() {
}
private CaretUpdater(EditPartViewer viewer, IEntity selectedEntity, int start, int end, Point location) {
this.viewer = viewer;
this.selectedEntity = selectedEntity;
this.start = start;
this.end = end;
this.location = location;
}
public static CaretUpdater record(EditPartViewer viewer) {
ITextualEntityPart focusPart = getFocusedTextualPart(viewer);
if (focusPart == null)
return NULL_UPDATER;
int start,end;
if (focusPart.hasSelectionRange()) {
start = focusPart.getSelectionStart();
end = focusPart.getSelectionEnd();
} else
start = end = focusPart.getCaretPosition();
return createCU(viewer, focusPart.getModelEntity(), start, end);
}
private static ITextualEntityPart getFocusedTextualPart(EditPartViewer viewer) {
if (viewer == null)
return null;
EditPart part = viewer.getFocusEditPart();
return part instanceof ITextualEntityPart ? (ITextualEntityPart) part : null;
}
public static CaretUpdater createCU(EditPartViewer viewer, IEntity selectedEntity, int start, int end) {
if (isValid(viewer, selectedEntity, start, end, null))
return new CaretUpdater(viewer, selectedEntity, start, end, null);
else
return NULL_UPDATER;
}
public static CaretUpdater createCU(EditPartViewer viewer, IEntity selectedEntity, int position) {
if (isValid(viewer, selectedEntity, position, position, null))
return new CaretUpdater(viewer, selectedEntity, position, position, null);
else
return NULL_UPDATER;
}
public static CaretUpdater createCU(EditPartViewer viewer, IEntity selectedEntity, Point location) {
if (isValid(viewer, selectedEntity, -1, -1, location))
return new CaretUpdater(viewer, selectedEntity, -1, -1, location);
else
return NULL_UPDATER;
}
private static final boolean isValid(EditPartViewer viewer, IEntity selectedEntity, int start, int end, Point location) {
return viewer != null && selectedEntity != null && ((start != -1 && end != -1) || location != null);
}
public static void sheduleSyncUpdate(EditPartViewer viewer, IEntity selectedEntity, int position, boolean deselectAll) {
sheduleSyncUpdate(viewer, selectedEntity, position, position, null, deselectAll);
}
public static void sheduleSyncUpdate(EditPartViewer viewer, IEntity selectedEntity, Point location, boolean deselectAll) {
sheduleSyncUpdate(viewer, selectedEntity, -1, -1, location, deselectAll);
}
public static void sheduleSyncUpdate(EditPartViewer viewer, IEntity selectedEntity, int start, int end, Point location, boolean deselectAll) {
EditPart entityPart = (EditPart) viewer.getEditPartRegistry().get(selectedEntity);
updateCaret(entityPart, viewer, start, end, location, deselectAll);
}
@SuppressWarnings("unchecked")
public void sheduleSyncUpdate() {
EditPart entityPart = ModelObserver.getObserver(selectedEntity, viewer.getEditPartRegistry());
updateCaret(entityPart, viewer, start, end, location, deselectAll);
}
public void sheduleAsyncUpdate() {
viewer.getControl().getDisplay().asyncExec(new Runnable() {
public void run() {
sheduleSyncUpdate();
}
});
}
public void afterUpdate(EntityPartEvent event) {
if (Matcher.find(selectedEntity, event.getEntityPart().getModelEntity(), false) != null) {
((IEntityPartViewer) viewer).removeEntityPartListener(this);
sheduleSyncUpdate();
}
}
@SuppressWarnings("unchecked")
private static void updateCaret(final EditPart entityPart, EditPartViewer viewer, int start, int end, Point location, boolean deselectAll) {
if (entityPart instanceof ITextualEntityPart) {
List<EditPart> selectedParts = viewer.getSelectedEditParts();
if (deselectAll && !selectedParts.isEmpty())
viewer.deselectAll();
viewer.setFocus(entityPart);
ITextualEntityPart caretPart = ((ITextualEntityPart)entityPart);
if (start != -1 && end != -1) {
caretPart.setCaretPosition(end);
if (start != end) {
caretPart.setSelectionRange(start, end);
viewer.appendSelection(caretPart);
}
} else if (location != null)
caretPart.updateCaret(location);
}
}
}