package com.project.website.canvas.client.worksheet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import com.google.common.base.Objects;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.project.shared.client.events.SimpleEvent;
import com.project.shared.client.events.SimpleEvent.Handler;
import com.project.shared.client.handlers.RegistrationsManager;
import com.project.shared.client.utils.ElementUtils;
import com.project.shared.client.utils.UrlUtils;
import com.project.shared.client.utils.ZIndexAllocator;
import com.project.shared.client.utils.widgets.DialogWithZIndex;
import com.project.shared.data.Pair;
import com.project.shared.data.Point2D;
import com.project.shared.data.funcs.AsyncFunc;
import com.project.shared.data.funcs.Func;
import com.project.shared.utils.GenericUtils;
import com.project.shared.utils.QueryString;
import com.project.shared.utils.StringUtils;
import com.project.shared.utils.ThrowableUtils;
import com.project.website.canvas.client.ToolFactories;
import com.project.website.canvas.client.canvastools.base.CanvasToolFrameImpl;
import com.project.website.canvas.client.canvastools.base.interfaces.CanvasTool;
import com.project.website.canvas.client.canvastools.base.interfaces.CanvasToolFactory;
import com.project.website.canvas.client.canvastools.base.interfaces.CanvasToolFrame;
import com.project.website.canvas.client.canvastools.base.interfaces.ToolboxItem;
import com.project.website.canvas.client.canvastools.image.ImageTool;
import com.project.website.canvas.client.canvastools.image.ImageToolFactory;
import com.project.website.canvas.client.shared.ImageOptionTypes;
import com.project.website.canvas.client.shared.ImageOptionsProviderUtils;
import com.project.website.canvas.client.shared.UndoManager;
import com.project.website.canvas.client.worksheet.interfaces.Worksheet;
import com.project.website.canvas.client.worksheet.interfaces.WorksheetView;
import com.project.website.canvas.client.worksheet.interfaces.WorksheetView.ImageDropInfo;
import com.project.website.canvas.client.worksheet.interfaces.WorksheetView.OperationStatus;
import com.project.website.canvas.client.worksheet.interfaces.WorksheetView.ToolCreationRequest;
import com.project.website.canvas.shared.contracts.CanvasService;
import com.project.website.canvas.shared.contracts.CanvasServiceAsync;
import com.project.website.canvas.shared.data.CanvasPage;
import com.project.website.canvas.shared.data.CanvasPageOptions;
import com.project.website.canvas.shared.data.ElementData;
import com.project.website.canvas.shared.data.Transform2D;
import com.project.website.shared.client.widgets.MessageBox;
import com.project.website.shared.client.widgets.authentication.invite.InviteWidget;
import com.project.website.shared.client.widgets.authentication.invite.InviteWidget.InviteRequestData;
import com.project.website.shared.contracts.authentication.AuthenticationService;
import com.project.website.shared.contracts.authentication.AuthenticationServiceAsync;
import com.project.website.shared.data.QueryParameters;
public class WorksheetImpl implements Worksheet
{
private CanvasPage page = new CanvasPage();
private final SimpleEvent<Void> _defaultToolboxItemRequestEvent = new SimpleEvent<Void>();
private final SimpleEvent<Boolean> viewModeEvent = new SimpleEvent<Boolean>();
private final WorksheetView view;
private final HashMap<CanvasTool<?>, ToolInstanceInfo> toolInfoMap = new HashMap<CanvasTool<?>, ToolInstanceInfo>();
private CanvasTool<?> activeToolInstance;
private ToolboxItem activeToolboxItem;
private ArrayList<ElementData> _toolClipboard = new ArrayList<ElementData>();
private final RegistrationsManager viewModeRegistrations = new RegistrationsManager();
private boolean _inViewMode = false;
//TODO: Think about something else. (Hadas)
private final WorksheetImageOptionsProvider _imageOptionsProvider = new WorksheetImageOptionsProvider();
private AsyncFunc<Void,Void> newPageAction = AsyncFunc.fromFunc(new Func.VoidAction(){
@Override public void exec() {
navigateToNewPage();
}});
public WorksheetImpl(WorksheetView view)
{
super();
this.view = view;
//AuthenticationServiceAsync service = getAuthService();
//updateUserSpecificInfo(view, service);
this.setRegistrations();
this.setDefaultPageOptions();
}
@Override
public HandlerRegistration addDefaultToolboxItemRequestHandler(SimpleEvent.Handler<Void> handler)
{
return _defaultToolboxItemRequestEvent.addHandler(handler);
}
@Override
public HandlerRegistration addViewModeChangedHandler(Handler<Boolean> handler)
{
return this.viewModeEvent.addHandler(handler);
}
@Override
public void load(String idStr, String pageKey)
{
load(parsePageIdStr(idStr), pageKey);
}
@Override
public void load(String idStr, boolean viewMode, String pageKey) {
if (viewMode) {
this.setModeView();
}
else {
this.setModeEdit();
}
this.load(idStr, pageKey);
}
@Override
public void save()
{
this.getSaveFunc()
.run(null);
}
public AsyncFunc<Void, CanvasPage> getSaveFunc()
{
return new AsyncFunc<Void, CanvasPage>() {
@Override protected <S, E> void run(Void arg,
Func<CanvasPage, S> successHandler,
Func<Throwable, E> errorHandler)
{
performSave(successHandler, errorHandler);
}};
}
protected enum NewPageDialogResults {
CANCEL,
NEW_BUT_SAVE_FIRST,
NEW_WITHOUT_SAVING,
}
protected class NewPageResultLabels extends Pair<NewPageDialogResults, String> {
private static final long serialVersionUID = 1L;
public NewPageResultLabels(NewPageDialogResults a, String b) { super(a, b); }
}
protected void newPage() {
final WorksheetImpl that = this;
AsyncFunc<Void, NewPageDialogResults> shouldSaveFirst = null;
if (this.currentPageIsEditable()) {
shouldSaveFirst = MessageBox.<NewPageDialogResults>getShowFunc(
"Save before leaving page?",
"Do you want to save your changes before leaving this page? If not, any unsaved changes will be gone forever.",
new NewPageResultLabels[] {
new NewPageResultLabels(NewPageDialogResults.NEW_BUT_SAVE_FIRST, "Save & New"),
new NewPageResultLabels(NewPageDialogResults.NEW_WITHOUT_SAVING, "Don't save, just start a new page"),
new NewPageResultLabels(NewPageDialogResults.CANCEL, "Cancel - stay on current page"),
},
NewPageDialogResults.NEW_BUT_SAVE_FIRST);
}
else {
shouldSaveFirst = AsyncFunc.constFunc(NewPageDialogResults.NEW_BUT_SAVE_FIRST);
}
shouldSaveFirst.thenSelect(new Func<NewPageDialogResults, AsyncFunc<NewPageDialogResults,Void>>() {
@Override public AsyncFunc<NewPageDialogResults, Void> apply(NewPageDialogResults arg) {
switch (arg) {
case NEW_BUT_SAVE_FIRST:
return that.getSaveFunc()
.<Void>constResult(null)
.then(newPageAction)
.constArg(null);
case NEW_WITHOUT_SAVING:
return newPageAction.constArg(null);
case CANCEL:
return AsyncFunc.constFunc(null);
default: throw new RuntimeException();
}}})
.run(null);
}
private void navigateToNewPage() {
History.newItem("");
this.load(new CanvasPage());
}
private boolean currentPageIsEditable() {
return pageIsEditable(this.page);
}
private static boolean pageIsEditable(CanvasPage page) {
// If page has no id, it's a new page and we can do whatever we want (edit and save it)
// If the page has an id but also has a key, then again we can save it.
return (null == page.id) || (false == StringUtils.isWhitespaceOrNull(page.key));
}
@Override
public void setActiveToolboxItem(ToolboxItem toolboxItem)
{
this.view.setActiveToolboxItem(toolboxItem);
if (toolboxItem == this.activeToolboxItem) {
return;
}
this.activeToolboxItem = toolboxItem;
if (null != this.activeToolboxItem.getToolFactory())
{
this.setActiveToolInstance(null);
}
}
private QueryString buildPageQueryString(Long pageId, String key, boolean viewMode)
{
QueryString query = QueryString.create(UrlUtils.getUrlEncoder());
if (null != pageId) {
query.append(QueryParameters.PAGE_ID, pageId);
}
if (null != key) {
query.append(QueryParameters.PAGE_KEY, key);
}
if (viewMode) {
query.append(QueryParameters.VIEW_MODE_FLAG, (String)null);
}
return query;
}
private String buildPageUrl(long pageId, String key, boolean viewMode)
{
QueryString query = buildPageQueryString(pageId, key, viewMode);
String newURL = Window.Location.createUrlBuilder().setHash(query.toString()).buildString();
return newURL;
}
private void clearActiveToolboxItem()
{
view.clearActiveToolboxItem();
}
private void copyToolsToClipboard(Collection<CanvasToolFrame> toolFrames)
{
this._toolClipboard.clear();
for (CanvasToolFrame toolFrame : toolFrames)
{
this.updateToolData(toolFrame);
ElementData data = toolFrame.getTool().getValue();
this._toolClipboard.add(data.getCloneable().getClone());
}
}
private CanvasToolFrame createToolInstance(final Point2D relativePos,
CanvasToolFactory<? extends CanvasTool<? extends ElementData>> toolFactory)
{
return this.createToolInstance(new Transform2D(relativePos, null, 0), toolFactory, true);
}
private CanvasToolFrameImpl createToolInstance(final Transform2D transform,
CanvasToolFactory<? extends CanvasTool<? extends ElementData>> toolFactory, boolean useCreationOffset)
{
final CanvasTool<? extends ElementData> tool = toolFactory.create();
final CanvasToolFrameImpl toolFrame = new CanvasToolFrameImpl(tool);
ToolInstanceInfo toolInfo = new ToolInstanceInfo(toolFactory, toolFrame, null);
this.toolInfoMap.put(tool, toolInfo);
RegistrationsManager regs = registerToolInstanceHandlers(toolFrame, toolInfo);
Point2D creationOffset = useCreationOffset ? toolFactory.getCreationOffset() : Point2D.zero;
view.addToolInstanceWidget(toolFrame, transform, creationOffset, true);
toolInfo.killRegistration = tool.getToolEvents().addKillRequestEventHandler(
new SimpleEvent.Handler<Void>() {
@Override
public void onFire(Void arg)
{
removeToolInstance(toolFrame);
}
});
regs.add(toolInfo.killRegistration);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute()
{
// TODO: Set zIndex according to the data instead.
ZIndexAllocator.allocateSetZIndex(toolFrame.getElement());
}
});
tool.bind();
tool.setViewMode(this._inViewMode);
return toolFrame;
}
private CanvasToolFrameImpl createToolInstanceFromData(ElementData newElement)
{
CanvasToolFactory<? extends CanvasTool<? extends ElementData>> factory = ToolFactories.INSTANCE.get(newElement.factoryUniqueId);
CanvasToolFrameImpl toolFrame = this.createToolInstance(newElement.transform, factory, false);
toolFrame.setViewMode(this._inViewMode);
toolFrame.getTool().setElementData(newElement);
toolFrame.setActive(false);
return toolFrame;
}
private void escapeOperation()
{
this.clearActiveToolboxItem();
this.setActiveToolInstance(null);
this.view.clearToolFrameSelection();
// TODO dispatch stop operation
// stopOperationEvent.dispatch(null);
this._defaultToolboxItemRequestEvent.dispatch(null);
}
private AuthenticationServiceAsync getAuthService()
{
AuthenticationServiceAsync service =
(AuthenticationServiceAsync)GWT.create(AuthenticationService.class);
return service;
}
private void invite()
{
final DialogWithZIndex dialog = new DialogWithZIndex(false, true);
final InviteWidget regWidget = new InviteWidget();
dialog.add(regWidget);
regWidget.addInviteRequestHandler(new SimpleEvent.Handler<InviteRequestData>() {
@Override
public void onFire(InviteRequestData arg)
{
regWidget.setEnabled(false);
inviteRequest(dialog, arg);
}
});
regWidget.addCancelRequestHandler(new Handler<Void>() {
@Override
public void onFire(Void arg)
{
dialog.hide();
}
});
dialog.setText("Invite a friend to PopSimple.com");
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute()
{
dialog.center();
}
});
}
private void inviteRequest(final DialogWithZIndex dialog, InviteRequestData arg)
{
AuthenticationServiceAsync service = getAuthService();
service.invite(arg.getEmail(), arg.getMessage(), arg.getName(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught)
{
Window.alert("Error: " + caught.toString());
dialog.hide();
}
@Override
public void onSuccess(Void result)
{
Window.alert("Invite sent!");
dialog.hide();
}
});
}
private void load(CanvasPage newPage)
{
UndoManager.get().clear();
this.replaceCurrentPage(newPage);
if (false == WorksheetImpl.pageIsEditable(newPage)) {
List<ElementData> elements = newPage.elements;
newPage.elements = new ArrayList<ElementData>();
// TODO: elements may contain sub-objects in them that are also persisted with an ID. So this cloning may not ensure
// that saving the elements later won't overwrite that data.
for (ElementData elem : elements)
{
newPage.elements.add(elem.getCloneable().getClone());
}
}
this.view.setPageEditable(this.currentPageIsEditable());
view.setOptions(newPage.options);
this.updateHistoryToken();
HashMap<String, ElementData> newElements = new HashMap<String, ElementData>();
for (ElementData elem : this.page.elements) {
newElements.put(elem.uniqueId, elem);
}
HashSet<Entry<CanvasTool<? extends ElementData>, ToolInstanceInfo>> entries =
new HashSet<Entry<CanvasTool<? extends ElementData>, ToolInstanceInfo>>(toolInfoMap.entrySet());
// Update existing and remove deleted tools
for (Entry<CanvasTool<? extends ElementData>, ToolInstanceInfo> entry : entries) {
CanvasTool<? extends ElementData> tool = entry.getKey();
ToolInstanceInfo toolInfo = entry.getValue();
ElementData oldData = tool.getValue();
ElementData newData = newElements.get(oldData.uniqueId);
if (null != newData) {
tool.setElementData(newData);
view.setToolFrameTransform(toolInfo.toolFrame, newData.transform, Point2D.zero);
newElements.remove(oldData.uniqueId);
} else {
this.removeToolInstance(toolInfo.toolFrame);
}
}
// Create the new tool instances
for (ElementData newElement : this.sortByZIndex(newElements.values())) {
this.createToolInstanceFromData(newElement);
}
}
private void replaceCurrentPage(CanvasPage newPage) {
// The server never send us the page key, unless this is the first time the page is saved.
// To make sure we don't lose the key we save it aside first.
String key = this.page.key;
this.page = newPage;
// If the loaded page doesn't contain a key, but has the same ID as the current page, reuse the same key
if ((null != this.page) && (GenericUtils.areEqual(newPage.id, this.page.id)) && (null == newPage.key))
{
// If our current page has the same id as the newly loaded page, use the same key
this.page.key = key;
}
}
private void load(Long id, String pageKey)
{
CanvasServiceAsync service = (CanvasServiceAsync) GWT.create(CanvasService.class);
this.updateViewForPageId(id, pageKey);
if (null == id) {
if (null != this.page.id) {
id = this.page.id;
}
else {
// Trying to reload when page wasn't yet saved. Might as well do nothing.
return;
}
}
if (Objects.equal(id, this.page.id)) {
return;
}
if (null != this.page.id)
{
// Page is being replaced.
this.page = new CanvasPage();
}
if (StringUtils.isWhitespaceOrNull(this.page.key)) {
this.page.key = pageKey;
}
view.onLoadOperationChange(OperationStatus.PENDING, null);
service.getPage(id, new AsyncCallback<CanvasPage>() {
@Override
public void onFailure(Throwable caught)
{
view.onLoadOperationChange(OperationStatus.FAILURE, caught.toString());
}
@Override
public void onSuccess(CanvasPage result)
{
if (null == result) {
view.onLoadOperationChange(OperationStatus.FAILURE, "Page not found");
return;
}
view.onLoadOperationChange(OperationStatus.SUCCESS, null);
load(result);
}
});
}
private void updateViewForPageId(Long id, String key)
{
this.view.setViewLinkTargetHistoryToken(this.buildPageQueryString(id, null, true).toString());
}
private void logout()
{
AuthenticationServiceAsync service = getAuthService();
service.logout(new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(Void result) {
Window.Location.reload();
}
});
}
private Long parsePageIdStr(String idStr)
{
Long id = null;
if ((null != idStr) && (false == idStr.trim().isEmpty()))
{
try {
id = Long.valueOf(idStr);
} catch (NumberFormatException e) {
return null;
}
}
return id;
}
private void pasteToolsFromClipboard()
{
if (this._toolClipboard.isEmpty())
{
return;
}
view.clearToolFrameSelection();
for (ElementData data : _toolClipboard)
{
ElementData offsetData = data.getCloneable().getClone();
//TODO: does it make sense that the Worksheet will add the offset?
offsetData.transform.translation =
offsetData.transform.translation.plus(new Point2D(10, 10));
view.selectToolFrame(createToolInstanceFromData(offsetData));
}
}
private RegistrationsManager registerToolInstanceHandlers(final CanvasToolFrameImpl toolFrame,
ToolInstanceInfo toolInfo)
{
RegistrationsManager regs = toolInfo.registrations;
regs.add(toolFrame.addCloseRequestHandler(new SimpleEvent.Handler<Void>() {
@Override public void onFire(Void arg) {
removeToolInstance(toolFrame);
}
}));
regs.add(toolFrame.addMoveBackRequestHandler(new SimpleEvent.Handler<Void>() {
@Override public void onFire(Void arg) {
ZIndexAllocator.moveElementBelow(toolFrame.getElement());
}
}));
regs.add(toolFrame.addMoveFrontRequestHandler(new SimpleEvent.Handler<Void>() {
@Override public void onFire(Void arg) {
ZIndexAllocator.moveElementAbove(toolFrame.getElement());
}
}));
return regs;
}
private void removeToolInstance(CanvasToolFrame toolFrame)
{
ZIndexAllocator.deallocateZIndex(toolFrame.asWidget().getElement());
ToolInstanceInfo info = this.toolInfoMap.remove(toolFrame.getTool());
view.removeToolInstanceWidget(toolFrame);
info.registrations.clear();
}
private void removeToolInstances(ArrayList<CanvasToolFrame> toolFrames)
{
for (CanvasToolFrame toolFrame : toolFrames)
{
this.removeToolInstance(toolFrame);
}
}
private void setActiveToolInstance(CanvasToolFrame toolFrame)
{
CanvasTool<?> tool = toolFrame != null ? toolFrame.getTool() : null;
if (tool == this.activeToolInstance) {
if (null != tool) {
// Even if the current tool is already active, notify it, because
// it may need to re-capture focus.
toolFrame.setActive(true);
}
return;
}
if (null != this.activeToolInstance) {
ToolInstanceInfo toolInfo = this.toolInfoMap.get(this.activeToolInstance);
if (null != toolInfo)
{
toolInfo.toolFrame.setActive(false);
}
}
this.activeToolInstance = tool;
if (null != toolFrame) {
toolFrame.setActive(true);
this.view.selectToolFrame(toolFrame);
}
}
private void setModeEdit()
{
if (false == this._inViewMode) {
return;
}
this.view.setViewMode(false);
this.viewModeEvent.dispatch(false);
this.viewModeRegistrations.clear();
this._inViewMode = false;
}
private void setModeView()
{
if (this._inViewMode) {
return;
}
this._inViewMode = true;
viewModeEvent.dispatch(true);
view.setViewMode(true);
viewModeRegistrations.add(view.addStopOperationHandler(new SimpleEvent.Handler<Void>() {
@Override public void onFire(Void arg) {
setModeEdit();
updateHistoryToken();
}
}));
}
private void setRegistrations()
{
view.addToolCreationRequestHandler(new Handler<WorksheetView.ToolCreationRequest>() {
@Override public void onFire(ToolCreationRequest arg) {
handleToolCreationRequest(arg);
}
});
view.addSaveHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
save();
}
});
view.addNewPageHandler(new Handler<Void>(){
@Override public void onFire(Void arg) {
newPage();
}
});
view.addLogoutHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
logout();
}
});
view.addInviteHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
invite();
}
});
view.addAddSpaceHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
}
});
/*
// TODO: Allow passing a pageKey here too
view.addLoadHandler(new Handler<String>() {
@Override public void onFire(String idStr) {
updateLoadedPageURL(idStr);
}
});*/
view.addCopyToolHandler(new Handler<ArrayList<CanvasToolFrame>>() {
@Override public void onFire(ArrayList<CanvasToolFrame> arg) {
copyToolsToClipboard(arg);
}
});
view.addPasteToolHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
pasteToolsFromClipboard();
}
});
view.addOptionsUpdatedHandler(new Handler<CanvasPageOptions>() {
@Override public void onFire(CanvasPageOptions arg) {
updateOptions(arg);
}
});
view.addStopOperationHandler(new Handler<Void>() {
@Override public void onFire(Void arg) {
escapeOperation();
}
});
view.addActiveToolFrameChangedHandler(new Handler<CanvasToolFrame>() {
@Override public void onFire(CanvasToolFrame frame) {
setActiveToolInstance(frame);
}
});
view.addRemoveToolsRequest(new Handler<ArrayList<CanvasToolFrame>>() {
@Override public void onFire(ArrayList<CanvasToolFrame> arg) {
removeToolInstances(arg);
}
});
view.addImageDropHandler(new Handler<WorksheetView.ImageDropInfo>() {
@Override public void onFire(ImageDropInfo arg) {
addImageFromDragAndDrop(arg);
}});
}
protected void addImageFromDragAndDrop(ImageDropInfo imageDropInfo) {
ImageTool imageTool = ImageToolFactory.INSTANCE.create();
imageTool.getValue().imageInformation.setUrl(imageDropInfo.getDataUrl());
imageTool.getValue().transform.translation = imageDropInfo.getPosition();
this.setActiveToolInstance(this.createToolInstanceFromData(imageTool.getValue()));
}
private Collection<ElementData> sortByZIndex(Collection<ElementData> elements)
{
TreeMap<Integer, ElementData> elementsByZIndex = new TreeMap<Integer, ElementData>();
for (ElementData element : elements) {
elementsByZIndex.put(element.zIndex, element);
}
return elementsByZIndex.values();
}
private void updateHistoryToken()
{
Long id = null;
String key = null;
if (null != this.page) {
id = this.page.id;
key = this.page.key;
}
History.newItem(this.buildPageQueryString(id, key, this._inViewMode).toString(), false);
this.updateViewForPageId(id, key);
}
/*
private void updateLoadedPageURL(String idStr)
{
Long id = parsePageIdStr(idStr);
if (null == id) {
return;
}
if (false == Objects.equal(this.page.id, id)) {
// Page id changed.
// Change the URL hash and trigger a history load event.
Window.Location.replace(this.buildPageUrl(id, this._inViewMode));
return;
}
// Page id not changed, just reload
this.load(idStr, ???);
}
*/
private void setDefaultPageOptions()
{
this.page.options.backgroundImage.options = ImageOptionsProviderUtils.getImageOptions(
this._imageOptionsProvider, ImageOptionTypes.OriginalSize);
view.setOptions(this.page.options);
}
private void updateOptions(CanvasPageOptions value)
{
if (null == value) {
return;
}
this.page.options = value;
view.setOptions(value);
}
private void updateToolData(CanvasToolFrame toolFrame){
ElementData toolData = toolFrame.getTool().getValue();
Element frameElement = toolFrame.asWidget().getElement();
toolData.zIndex = ZIndexAllocator.getElementZIndex(frameElement);
toolData.transform = new Transform2D(ElementUtils.getElementOffsetPosition(frameElement),
toolFrame.getToolSize(), ElementUtils.getRotation(frameElement));
}
/*
private void updateUserSpecificInfo(WorksheetView view, AuthenticationServiceAsync service)
{
this.view.setUserProfile(null);
final WorksheetImpl that = this;
service.getUserProfile(new AsyncCallback<UserProfile>() {
@Override public void onFailure(Throwable caught)
{
// TODO: handle
}
@Override public void onSuccess(UserProfile result)
{
that.view.setUserProfile(result);
}
});
}*/
private void handleToolCreationRequest(ToolCreationRequest toolCreationRequest)
{
CanvasToolFactory<? extends CanvasTool<? extends ElementData>> factory = toolCreationRequest.getFactory();
if (null == factory) {
return;
}
CanvasToolFrame toolFrame = createToolInstance(toolCreationRequest.getPosition(), factory);
setActiveToolInstance(toolFrame);
if (toolCreationRequest.getFactory().isOneShot()) {
_defaultToolboxItemRequestEvent.dispatch(null);
}
else
{
setActiveToolboxItem(activeToolboxItem);
}
toolCreationRequest.toolCreated(toolFrame.getTool());
}
private <S, E> void performSave(final Func<CanvasPage, S> successHandler, final Func<Throwable, E> errorHandler)
{
// TODO: Defrag zIndex of all tools before saving.
ArrayList<ElementData> activeElems = new ArrayList<ElementData>();
for (Entry<CanvasTool<? extends ElementData>, ToolInstanceInfo> entry : toolInfoMap.entrySet()) {
ToolInstanceInfo toolInfo = entry.getValue();
this.updateToolData(toolInfo.toolFrame);
activeElems.add(toolInfo.toolFrame.getTool().getValue());
}
this.page.elements.clear();
this.page.elements.addAll(activeElems);
if (false == this.currentPageIsEditable()) {
// Make sure the service generates a new id and key for this page
this.page.id = null;
this.page.key = null;
}
CanvasServiceAsync service = (CanvasServiceAsync) GWT.create(CanvasService.class);
view.onSaveOperationChange(OperationStatus.PENDING, null);
service.savePage(page, new AsyncCallback<CanvasPage>() {
@Override
public void onFailure(Throwable caught)
{
view.onSaveOperationChange(OperationStatus.FAILURE,
ThrowableUtils.joinStackTrace(caught));
errorHandler.apply(caught);
}
@Override
public void onSuccess(CanvasPage result)
{
// TODO: see issue #92
load(result);
view.onSaveOperationChange(OperationStatus.SUCCESS, null);
Window.Location.replace(buildPageUrl(result.id, result.key, false));
successHandler.apply(result);
}
});
}
}