/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.internal.handlers;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.handlers.HandlerUtil;
import com.rcpcompany.uibindings.Constants;
import com.rcpcompany.uibindings.IBindingContext;
import com.rcpcompany.uibindings.IBindingContext.FinishOption;
import com.rcpcompany.uibindings.IContainerBinding;
import com.rcpcompany.uibindings.IManager;
import com.rcpcompany.uibindings.IUIAttribute;
import com.rcpcompany.uibindings.IUIBindingsPackage;
import com.rcpcompany.uibindings.IValueBinding;
import com.rcpcompany.uibindings.IValueBindingCell;
import com.rcpcompany.uibindings.IViewerBinding;
import com.rcpcompany.uibindings.internal.Activator;
import com.rcpcompany.uibindings.model.utils.ICommandStackWithCollect;
import com.rcpcompany.uibindings.uiAttributes.SimpleUIAttribute;
import com.rcpcompany.uibindings.utils.IBindingHighlightContext;
import com.rcpcompany.uibindings.utils.IBindingHighlightContext.STAGE;
import com.rcpcompany.uibindings.utils.IClipboardConverterManager;
import com.rcpcompany.uibindings.utils.IClipboardConverterManager.IResult;
import com.rcpcompany.utils.logging.LogUtils;
/**
* Handler for <code>com.rcpcompany.uibindings.commands.SuperPaste</code> for within
* {@link IViewerBinding}...
*
* @author Tonny Madsen, The RCP Company
*/
public class ViewerSuperPasteHandler extends AbstractHandler implements IHandler {
@Override
public Object execute(ExecutionEvent event) {
if (Activator.getDefault().TRACE_HANDLERS) {
LogUtils.debug(this, "");
}
final IValueBinding binding = (IValueBinding) HandlerUtil.getVariable(event, Constants.SOURCES_ACTIVE_BINDING);
if (binding == null) return null;
final IBindingContext context = binding.getContext();
final List<IResult> conversions = IClipboardConverterManager.Factory.getManager().getClipboardConversions();
if (conversions.size() == 0) {
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data",
"Data format of the pasted data is not supported");
return null;
}
/*
* Just select the first
*/
final IResult result = conversions.get(0);
// for (final String[] l : result) {
// LogUtils.debug(this, "line: " + Arrays.toString(l));
// }
// LogUtils.debug(this, result.getConverterNames() + ": " + result.getColumns() + "x" +
// result.getRows());
final int rows = result.getRows();
final int columns = result.getColumns();
final String[][] table = result.getTable();
/*
* Check that we have room for the paste...
*/
final IValueBindingCell baseCell = binding.getCell();
if (baseCell == null) {
LogUtils.error(binding, "Binding " + binding + " does not have a cell!");
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data", "Internal Error");
return null;
}
final IContainerBinding container = baseCell.getContainer();
final Point p = baseCell.getPosition(true);
if (p == null) {
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data",
"Can only paste into a viewer");
return null;
}
final IBindingHighlightContext successHighlightContext = IBindingHighlightContext.Factory.createContext();
final Map<IValueBinding, String> assignmentMap = new HashMap<IValueBinding, String>();
final CommandStack commandStack = IManager.Factory.getManager().getEditingDomain().getCommandStack();
try {
if (commandStack instanceof ICommandStackWithCollect) {
((ICommandStackWithCollect) commandStack).setCollectCommandMode(true);
}
for (int r = 0; r < rows; r++) {
/*
* The index of the column to copy into - needed as some columns can be zero width
* and must be ignored
*/
int ci = p.x;
for (int c = 0; c < columns; c++) {
final String data = table[r][c];
IValueBindingCell cell;
do {
cell = container.getCell(ci, p.y + r, true);
ci++;
if (cell == null) {
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data",
"No room for data");
return null;
}
} while (cell.getColumnBinding() != null
&& cell.getColumnBinding().getColumnAdapter().getWidth() == 0);
final IValueBinding b = cell.getLabelBinding();
if (!b.isChangeable()) {
cell.setFocus();
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data",
"Target cell is not changeable");
return null;
}
successHighlightContext.add(b);
/*
* Make a new paste binding and add this to the assignmentMap...
*/
final WritableValue ov = new WritableValue("", String.class);
final IUIAttribute attribute = new SimpleUIAttribute(null, "", ov, true);
// TODO: Why are we sure about this being a value?
final IValueBinding pasteBinding = context.addBinding().model(b.getModelObservableValue())
.ui(attribute);
if (binding.hasArguments()) {
pasteBinding.getExtraArgumentProviders().add(b);
}
if (binding.getParentBinding() != null) {
pasteBinding.getExtraArgumentProviders().add(binding.getParentBinding());
}
if (binding.eIsSet(IUIBindingsPackage.Literals.BINDING__EXTRA_ARGUMENT_PROVIDERS)) {
pasteBinding.getExtraArgumentProviders().addAll(b.getExtraArgumentProviders());
}
pasteBinding.setCell(cell);
assignmentMap.put(pasteBinding, data);
}
}
/*
* Assign all values
*/
context.finish(FinishOption.FORCE);
for (final Entry<IValueBinding, String> d : assignmentMap.entrySet()) {
final IValueBinding b = d.getKey();
final String value = d.getValue();
b.getUIAttribute().getCurrentValue().setValue(value);
/*
* Check for errors in the binding
*/
final List<String> errors = b.getErrors();
if (errors != null && errors.size() > 0) {
b.getCell().setFocus();
// TODO Should concat to get all errors
// TODO highlight error bindings
/*
* Not really correct... Will allow the first set of changes...
*/
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Cannot paste data", "Setting value '"
+ value + "' : " + errors.get(0));
return null;
}
}
successHighlightContext.activate();
} finally {
if (commandStack instanceof ICommandStackWithCollect) {
((ICommandStackWithCollect) commandStack).setCollectCommandMode(false);
}
/*
* If we did not succeed, the dispose the highlight context...
*/
if (successHighlightContext.getStage() == STAGE.INIT) {
successHighlightContext.dispose();
}
/*
* Dispose all the created bindings
*/
for (final Entry<IValueBinding, String> d : assignmentMap.entrySet()) {
d.getKey().dispose();
}
}
return null;
}
}