/*
* Copyright 2015 JBoss, by Red Hat, Inc
*
* 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 org.uberfire.ext.wires.core.scratchpad.client.canvas;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.IsWidget;
import org.uberfire.client.annotations.WorkbenchMenu;
import org.uberfire.client.annotations.WorkbenchPartTitle;
import org.uberfire.client.annotations.WorkbenchPartView;
import org.uberfire.client.annotations.WorkbenchScreen;
import org.uberfire.ext.wires.core.api.containers.ContainerManager;
import org.uberfire.ext.wires.core.api.containers.RequiresContainerManager;
import org.uberfire.ext.wires.core.api.containers.WiresContainer;
import org.uberfire.ext.wires.core.api.events.ClearEvent;
import org.uberfire.ext.wires.core.api.events.ShapeAddedEvent;
import org.uberfire.ext.wires.core.api.events.ShapeDeletedEvent;
import org.uberfire.ext.wires.core.api.events.ShapeDragCompleteEvent;
import org.uberfire.ext.wires.core.api.events.ShapeDragPreviewEvent;
import org.uberfire.ext.wires.core.api.events.ShapeSelectedEvent;
import org.uberfire.ext.wires.core.api.shapes.WiresBaseShape;
import org.uberfire.ext.wires.core.api.shapes.WiresShape;
import org.uberfire.ext.wires.core.client.canvas.WiresCanvas;
import org.uberfire.mvp.Command;
import org.uberfire.workbench.model.menu.MenuFactory;
import org.uberfire.workbench.model.menu.Menus;
@SuppressWarnings("unused")
@Dependent
@WorkbenchScreen(identifier = "WiresScratchPadScreen")
public class WiresScratchPadScreen extends WiresCanvas implements ContainerManager {
@Inject
private Event<ClearEvent> clearEvent;
@Inject
private Event<ShapeSelectedEvent> shapeSelectedEvent;
@Inject
private Event<ShapeAddedEvent> shapeAddedEvent;
@Inject
private Event<ShapeDeletedEvent> shapeDeletedEvent;
private Menus menus;
private WiresScratchPadDropContext dropContext = new WiresScratchPadDropContext();
@PostConstruct
public void setup() {
this.menus = MenuFactory
.newTopLevelMenu("Clear grid")
.respondsWith(new Command() {
@Override
public void execute() {
clear();
}
})
.endMenu()
.newTopLevelMenu("Delete selected")
.respondsWith(new Command() {
@Override
public void execute() {
if (isShapeSelected()) {
deleteShape(getSelectedShape());
}
}
})
.endMenu()
.newTopLevelMenu("Clear selection")
.respondsWith(new Command() {
@Override
public void execute() {
if (isShapeSelected()) {
clearSelection();
menus.getItems().get(1).setEnabled(false);
menus.getItems().get(2).setEnabled(false);
}
}
})
.endMenu()
.build();
menus.getItems().get(0).setEnabled(false);
menus.getItems().get(1).setEnabled(false);
menus.getItems().get(2).setEnabled(false);
}
@WorkbenchPartTitle
@Override
public String getTitle() {
return "Canvas";
}
@WorkbenchPartView
public IsWidget getView() {
return this;
}
@WorkbenchMenu
public Menus getMenus() {
return menus;
}
@Override
public void selectShape(final WiresBaseShape shape) {
shapeSelectedEvent.fire(new ShapeSelectedEvent(shape));
}
public void onShapeSelected(@Observes ShapeSelectedEvent event) {
super.selectShape(event.getShape());
menus.getItems().get(1).setEnabled(isShapeSelected());
menus.getItems().get(2).setEnabled(isShapeSelected());
}
@Override
public void deselectShape(final WiresBaseShape shape) {
super.deselectShape(shape);
menus.getItems().get(1).setEnabled(isShapeSelected());
menus.getItems().get(2).setEnabled(isShapeSelected());
}
public void onDragPreviewHandler(@Observes ShapeDragPreviewEvent shapeDragPreviewEvent) {
//Only Shapes that require a ContainerManager can be dropped into Containers
if (!(shapeDragPreviewEvent.getShape() instanceof RequiresContainerManager)) {
dropContext.setContext(null);
return;
}
//Find a Container to drop the Shape into
final double cx = getX(shapeDragPreviewEvent.getX());
final double cy = getY(shapeDragPreviewEvent.getY());
final WiresContainer container = getContainer(cx,
cy);
dropContext.setContext(container);
canvasLayer.batch();
}
public void onDragCompleteHandler(@Observes ShapeDragCompleteEvent shapeDragCompleteEvent) {
final WiresBaseShape wiresShape = shapeDragCompleteEvent.getShape();
//If there's no Shape to add then exit
if (wiresShape == null) {
return;
}
//Get Shape's co-ordinates relative to the Canvas
final double cx = getX(shapeDragCompleteEvent.getX());
final double cy = getY(shapeDragCompleteEvent.getY());
//If the Shape was dropped outside the bounds of the Canvas then exit
if (cx < 0 || cy < 0) {
return;
}
if (cx > getOffsetWidth() || cy > getOffsetHeight()) {
return;
}
//Add Shape to Canvas
wiresShape.setX(cx);
wiresShape.setY(cy);
//If we're adding the Shape to a Container notify the Container of a new child. We cannot add Shape
//to the Container's underlying (impl) Group (which would be ideal) as we can no longer select the
//child separately from the Group. We therefore just keep a reference to children in the Container
//and move them when we move the Container
final WiresContainer container = dropContext.getContext();
if (container != null) {
container.attachShape(wiresShape);
container.setHover(false);
}
addShape(wiresShape);
//Enable clearing of Canvas now a Shape has been added
menus.getItems().get(0).setEnabled(true);
//Notify other Panels of a Shape being added
shapeAddedEvent.fire(new ShapeAddedEvent(wiresShape));
}
private double getX(double xShapeEvent) {
return xShapeEvent - getAbsoluteLeft();
}
private double getY(double yShapeEvent) {
return yShapeEvent - getAbsoluteTop();
}
@Override
public void clear() {
if (Window.confirm("Are you sure to clean the canvas?")) {
clearEvent.fire(new ClearEvent());
}
}
public void onClear(@Observes ClearEvent event) {
super.clear();
menus.getItems().get(0).setEnabled(false);
menus.getItems().get(1).setEnabled(false);
menus.getItems().get(2).setEnabled(false);
}
@Override
public void deleteShape(final WiresBaseShape shape) {
if (Window.confirm("Are you sure to remove the selected shape?")) {
shapeDeletedEvent.fire(new ShapeDeletedEvent(shape));
}
}
@Override
public void forceDeleteShape(final WiresBaseShape shape) {
shapeDeletedEvent.fire(new ShapeDeletedEvent(shape));
}
public void onShapeDeleted(@Observes ShapeDeletedEvent event) {
super.deleteShape(event.getShape());
menus.getItems().get(0).setEnabled(getShapesInCanvas().size() > 0);
menus.getItems().get(1).setEnabled(isShapeSelected());
menus.getItems().get(2).setEnabled(isShapeSelected());
}
@Override
public void addShape(final WiresBaseShape shape) {
super.addShape(shape);
//Attach relevant handlers
if (shape instanceof RequiresContainerManager) {
((RequiresContainerManager) shape).setContainerManager(this);
}
}
@Override
public WiresContainer getContainer(final double cx,
final double cy) {
WiresContainer container = null;
for (WiresShape ws : getShapesInCanvas()) {
if (ws instanceof WiresContainer) {
final WiresContainer wc = (WiresContainer) ws;
wc.setHover(false);
if (wc.contains(cx,
cy)) {
wc.setHover(true);
container = wc;
}
}
}
return container;
}
}