/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.stunner.client.lienzo.shape.view.ext;
import com.ait.lienzo.client.core.shape.Group;
import com.ait.lienzo.client.core.shape.IPrimitive;
import com.ait.lienzo.client.core.shape.Text;
import com.ait.lienzo.client.core.shape.wires.LayoutContainer;
import com.ait.lienzo.shared.core.types.ColorName;
import com.google.gwt.event.shared.HandlerRegistration;
import org.kie.workbench.common.stunner.client.lienzo.shape.view.ViewEventHandlerManager;
import org.kie.workbench.common.stunner.core.client.shape.view.HasTitle;
import org.kie.workbench.common.stunner.core.client.shape.view.event.TextClickEvent;
import org.kie.workbench.common.stunner.core.client.shape.view.event.TextDoubleClickEvent;
import org.kie.workbench.common.stunner.core.client.shape.view.event.TextEnterEvent;
import org.kie.workbench.common.stunner.core.client.shape.view.event.TextExitEvent;
import org.kie.workbench.common.stunner.core.client.shape.view.event.ViewEventType;
import org.kie.workbench.common.stunner.core.client.shape.view.event.ViewHandler;
/**
* A helper class for handling the wires shapes' text primitive
* that is used to display the shape's name.
* <p>
* It handles common logic for ShapeViews that implement <code>HasText</code>
* type, can be reused for shapes or connectors.
* <p>
*/
public class WiresTextDecorator {
private final ViewEventHandlerManager eventHandlerManager;
private final Group textContainer = new Group();
private ViewHandler<TextEnterEvent> textOverHandlerViewHandler;
private ViewHandler<TextExitEvent> textOutEventViewHandler;
private ViewHandler<TextClickEvent> textClickEventViewHandler;
private ViewHandler<TextDoubleClickEvent> textDblClickEventViewHandler;
private Text text;
private LayoutContainer.Layout currentTextLayout;
public WiresTextDecorator(final ViewEventHandlerManager eventHandlerManager) {
this.eventHandlerManager = eventHandlerManager;
initialize();
}
public void setTextClickHandler(final ViewHandler<TextClickEvent> textClickEventViewHandler) {
this.textClickEventViewHandler = textClickEventViewHandler;
}
public void setTextDblClickHandler(final ViewHandler<TextDoubleClickEvent> textDblClickEventViewHandler) {
this.textDblClickEventViewHandler = textDblClickEventViewHandler;
}
public void setTextEnterHandler(final ViewHandler<TextEnterEvent> textOverHandlerViewHandler) {
this.textOverHandlerViewHandler = textOverHandlerViewHandler;
}
public void setTextExitHandler(final ViewHandler<TextExitEvent> textOutEventViewHandler) {
this.textOutEventViewHandler = textOutEventViewHandler;
}
private void initialize() {
this.text = new Text("")
.setFontSize(14)
.setFillColor(ColorName.BLACK)
.setStrokeWidth(1)
.setDraggable(false)
.setAlpha(0);
this.currentTextLayout = LayoutContainer.Layout.CENTER;
textContainer.add(text);
// Ensure path bounds are available on the selection context.
text.setFillBoundsForSelection(true);
initializeHandlers();
}
private void initializeHandlers() {
registerTextEnterHandler();
registerTextExitHandler();
registerClickHandler();
registerDoubleClickHandler();
}
private void registerClickHandler() {
HandlerRegistration registration = text.addNodeMouseClickHandler(event -> {
if (null != textClickEventViewHandler) {
eventHandlerManager.skipClickHandler();
final TextClickEvent e = new TextClickEvent(event.getX(),
event.getY(),
event.getMouseEvent().getClientX(),
event.getMouseEvent().getClientY());
textClickEventViewHandler.handle(e);
eventHandlerManager.restoreClickHandler();
}
});
eventHandlerManager.addHandlersRegistration(ViewEventType.TEXT_CLICK,
registration);
}
private void registerDoubleClickHandler() {
HandlerRegistration registration = text.addNodeMouseDoubleClickHandler(event -> {
if (null != textDblClickEventViewHandler) {
eventHandlerManager.skipClickHandler();
final TextDoubleClickEvent e = new TextDoubleClickEvent(event.getX(),
event.getY(),
event.getMouseEvent().getClientX(),
event.getMouseEvent().getClientY());
textDblClickEventViewHandler.handle(e);
eventHandlerManager.restoreClickHandler();
}
});
eventHandlerManager.addHandlersRegistration(ViewEventType.TEXT_DBL_CLICK,
registration);
}
private void registerTextEnterHandler() {
HandlerRegistration registration = text.addNodeMouseEnterHandler(event -> {
if (null != textOverHandlerViewHandler && hasText()) {
final TextEnterEvent textOverEvent = new TextEnterEvent(event.getX(),
event.getY(),
event.getMouseEvent().getClientX(),
event.getMouseEvent().getClientY());
textOverHandlerViewHandler.handle(textOverEvent);
}
});
eventHandlerManager.addHandlersRegistration(ViewEventType.TEXT_ENTER,
registration);
}
private void registerTextExitHandler() {
HandlerRegistration registration = text.addNodeMouseExitHandler(event -> {
if (null != textOutEventViewHandler && hasText()) {
final TextExitEvent textOutEvent = new TextExitEvent(event.getX(),
event.getY(),
event.getMouseEvent().getClientX(),
event.getMouseEvent().getClientY());
textOutEventViewHandler.handle(textOutEvent);
}
});
eventHandlerManager.addHandlersRegistration(ViewEventType.TEXT_EXIT,
registration);
}
@SuppressWarnings("unchecked")
public void setTitle(final String title) {
text.setText(title);
}
@SuppressWarnings("unchecked")
public boolean setTitlePosition(final HasTitle.Position position) {
LayoutContainer.Layout layout = LayoutContainer.Layout.CENTER;
switch (position) {
case BOTTOM:
layout = LayoutContainer.Layout.BOTTOM;
break;
case TOP:
layout = LayoutContainer.Layout.TOP;
break;
case LEFT:
layout = LayoutContainer.Layout.LEFT;
break;
case RIGHT:
layout = LayoutContainer.Layout.RIGHT;
break;
}
final boolean changed = !currentTextLayout.equals(layout);
this.currentTextLayout = layout;
return changed;
}
@SuppressWarnings("unchecked")
public void setTitleRotation(final double degrees) {
text.setRotationDegrees(degrees);
}
@SuppressWarnings("unchecked")
public void setTitleStrokeColor(final String color) {
text.setStrokeColor(color);
}
@SuppressWarnings("unchecked")
public void setTitleFontFamily(final String fontFamily) {
text.setFontFamily(fontFamily);
}
@SuppressWarnings("unchecked")
public void setTitleFontSize(final double fontSize) {
text.setFontSize(fontSize);
}
@SuppressWarnings("unchecked")
public void setTitleAlpha(final double alpha) {
text.setAlpha(alpha);
}
@SuppressWarnings("unchecked")
public void setTitleStrokeWidth(final double strokeWidth) {
text.setStrokeWidth(strokeWidth);
}
@SuppressWarnings("unchecked")
public void moveTitleToTop() {
textContainer.moveToTop();
}
public IPrimitive<?> getView() {
return textContainer;
}
public LayoutContainer.Layout getLayout() {
return currentTextLayout;
}
public void destroy() {
if (null != text) {
text.removeFromParent();
this.text = null;
}
textContainer.removeFromParent();
deregisterHandler(textOverHandlerViewHandler);
deregisterHandler(textOutEventViewHandler);
deregisterHandler(textClickEventViewHandler);
deregisterHandler(textDblClickEventViewHandler);
}
private void deregisterHandler(final ViewHandler<?> handler) {
if (null != handler) {
eventHandlerManager.removeHandler(handler);
}
}
private boolean hasText() {
final String text = this.text.getText();
return null != text && text.trim().length() > 0;
}
}