/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.wkf.roleeditor;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.openflexo.fge.DrawingGraphicalRepresentation;
import org.openflexo.fge.FGEUtils;
import org.openflexo.fge.GraphicalRepresentation;
import org.openflexo.fge.ShapeGraphicalRepresentation;
import org.openflexo.fge.controller.DrawingController;
import org.openflexo.fge.cp.ControlArea;
import org.openflexo.fge.geom.FGEGeometricObject.Filling;
import org.openflexo.fge.geom.FGEGeometricObject.SimplifiedCardinalDirection;
import org.openflexo.fge.geom.FGEPoint;
import org.openflexo.fge.geom.FGERectangle;
import org.openflexo.fge.geom.FGERoundRectangle;
import org.openflexo.fge.geom.FGEShape;
import org.openflexo.fge.graphics.BackgroundStyle;
import org.openflexo.fge.graphics.BackgroundStyle.ColorGradient.ColorGradientDirection;
import org.openflexo.fge.graphics.FGEGraphics;
import org.openflexo.fge.graphics.ForegroundStyle;
import org.openflexo.fge.notifications.ObjectResized;
import org.openflexo.fge.view.DrawingView;
import org.openflexo.fge.view.FGEPaintManager;
import org.openflexo.fge.view.ShapeView;
import org.openflexo.foundation.wkf.FlexoWorkflow;
import org.openflexo.foundation.wkf.Role;
import org.openflexo.foundation.wkf.RoleList;
import org.openflexo.foundation.wkf.action.AddRole;
import org.openflexo.foundation.wkf.action.AddRoleSpecialization;
public class FloatingPalette extends ControlArea<FGERoundRectangle> implements Observer {
private static final Logger logger = Logger.getLogger(FloatingPalette.class.getPackage().getName());
protected static final Color OK = new Color(0, 191, 0);
private enum Mode {
ROLE, SPECIALIZATION;
}
private RoleGR roleGR;
private RoleList target;
private FGERoundRectangle roleRect;
private FGERectangle edgeRect;
/** The vertical space between two elements of the palette */
private static final int SPACING = 5;
/** The height of an element of the palette */
private static final int ELEMENTS_HEIGHT = 8;
/** The width of an element of the palette */
private static final int ELEMENTS_WIDTH = 12;
private static final ForegroundStyle NONE = ForegroundStyle.makeNone();
private static final BackgroundStyle DEFAULT = BackgroundStyle.makeColoredBackground(Color.WHITE);
private static final ForegroundStyle NODE_FOREGROUND = ForegroundStyle.makeStyle(Color.RED, 1.0f);
private static final ForegroundStyle EDGE_FOREGROUND = ForegroundStyle.makeStyle(FGEUtils.NICE_BROWN, 1.0f);
private static final BackgroundStyle NODE_BACKGROUND = BackgroundStyle.makeColorGradientBackground(Color.ORANGE, Color.WHITE,
ColorGradientDirection.SOUTH_EAST_NORTH_WEST);
static {
DEFAULT.setUseTransparency(true);
DEFAULT.setTransparencyLevel(0.3f);
NODE_BACKGROUND.setUseTransparency(true);
NODE_BACKGROUND.setTransparencyLevel(0.7f);
}
private SimplifiedCardinalDirection orientation;
public FloatingPalette(RoleGR roleGR, RoleList target, SimplifiedCardinalDirection orientation) {
super(roleGR, makeRoundRect(roleGR, orientation));
this.roleGR = roleGR;
this.target = target;
this.orientation = orientation;
roleGR.addObserver(this);
updateElements(orientation);
}
@Override
public boolean isDraggable() {
return roleGR.getDrawing().isEditable();
}
protected Point currentDraggingLocationInDrawingView = null;
protected boolean drawEdge = false;
protected boolean isDnd = false;
protected RoleGR to = null;
protected GraphicalRepresentation<?> focusedGR;
private RoleEditorController controller;
private FGEPoint normalizedStartPoint;
private Rectangle previousRectangle;
private Mode mode;
public void paint(Graphics g, RoleEditorController controller) {
if (drawEdge && currentDraggingLocationInDrawingView != null) {
FGEShape<?> fgeShape = roleGR.getShape().getOutline();
DrawingGraphicalRepresentation<?> drawingGR = controller.getDrawingGraphicalRepresentation();
double scale = controller.getScale();
FGEPoint nearestOnOutline = fgeShape.getNearestPoint(drawingGR.convertLocalViewCoordinatesToRemoteNormalizedPoint(
currentDraggingLocationInDrawingView, roleGR, scale));
/*nodeGR.convertLocalNormalizedPointToRemoteViewCoordinates(this.normalizedStartPoint, controller.getDrawingGraphicalRepresentation(), controller.getScale())*/
Point fromPoint = roleGR.convertLocalNormalizedPointToRemoteViewCoordinates(nearestOnOutline, drawingGR, scale);
Point toPoint = currentDraggingLocationInDrawingView;
if (mode == Mode.SPECIALIZATION) {
if (to != null && isDnd) {
// toPoint = drawingGR.convertRemoteNormalizedPointToLocalViewCoordinates(to.getShape().getShape().getCenter(), to,
// scale);
g.setColor(OK);
} else {
g.setColor(Color.RED);
}
} else {
if (isDnd) {
g.setColor(OK);
} else {
g.setColor(Color.RED);
}
}
g.drawLine(fromPoint.x, fromPoint.y, toPoint.x, toPoint.y);
int x, y, w, h;
if (fromPoint.x >= toPoint.x) {
x = toPoint.x;
w = fromPoint.x - toPoint.x;
} else {
x = fromPoint.x;
w = toPoint.x - fromPoint.x;
}
if (fromPoint.y >= toPoint.y) {
y = toPoint.y;
h = fromPoint.y - toPoint.y;
} else {
y = fromPoint.y;
h = toPoint.y - fromPoint.y;
}
previousRectangle = new Rectangle(x, y, w, h);
}
}
@Override
public void startDragging(DrawingController<?> controller, FGEPoint startPoint) {
mode = null;
if (roleRect.contains(startPoint)) {
mode = Mode.ROLE;
} else if (edgeRect.contains(startPoint)) {
mode = Mode.SPECIALIZATION;
}
if (mode != null) {
drawEdge = true;
normalizedStartPoint = startPoint;
this.controller = (RoleEditorController) controller;
((RoleEditorView) controller.getDrawingView()).setFloatingPalette(this);
} else {
drawEdge = false;
}
}
@Override
public boolean dragToPoint(FGEPoint newRelativePoint, FGEPoint pointRelativeToInitialConfiguration, FGEPoint newAbsolutePoint,
FGEPoint initialPoint, MouseEvent event) {
if (drawEdge) {
DrawingView<?> drawingView = controller.getDrawingView();
FGEPaintManager paintManager = drawingView.getPaintManager();
// Attempt to repaint relevant zone only
Rectangle oldBounds = previousRectangle;
if (oldBounds != null) {
oldBounds.x -= 1;
oldBounds.y -= 1;
oldBounds.width += 2;
oldBounds.height += 2;
}
focusedGR = controller.getDrawingView().getFocusRetriever().getFocusedObject(event);
if (focusedGR instanceof RoleGR && focusedGR != roleGR) {
to = (RoleGR) focusedGR;
} else {
to = null;
}
currentDraggingLocationInDrawingView = SwingUtilities.convertPoint((Component) event.getSource(), event.getPoint(),
controller.getDrawingView());
if (!isDnd) {
isDnd = roleGR.convertLocalNormalizedPointToRemoteViewCoordinates(normalizedStartPoint,
controller.getDrawingGraphicalRepresentation(), controller.getScale()).distance(
currentDraggingLocationInDrawingView) > 5;
}
// Attempt to repaint relevant zone only
Rectangle newBounds = getBoundsToRepaint(drawingView);
Rectangle boundsToRepaint;
if (oldBounds != null) {
boundsToRepaint = oldBounds.union(newBounds);
} else {
boundsToRepaint = newBounds;
}
paintManager.repaint(drawingView, boundsToRepaint);
// Alternative @brutal zone
// paintManager.repaint(drawingView);
return true;
}
return false;
}
// Attempt to repaint relevant zone only
private Rectangle getBoundsToRepaint(DrawingView<?> drawingView) {
ShapeView<?> fromView = drawingView.shapeViewForObject(roleGR);
Rectangle fromViewBounds = SwingUtilities.convertRectangle(fromView, fromView.getBounds(), drawingView);
Rectangle boundsToRepaint = fromViewBounds;
if (to != null) {
ShapeView<?> toView = drawingView.shapeViewForObject(to);
Rectangle toViewBounds = SwingUtilities.convertRectangle(toView, toView.getBounds(), drawingView);
boundsToRepaint = fromViewBounds.union(toViewBounds);
}
if (currentDraggingLocationInDrawingView != null) {
Rectangle lastLocationBounds = new Rectangle(currentDraggingLocationInDrawingView);
boundsToRepaint = fromViewBounds.union(lastLocationBounds);
}
// logger.fine("boundsToRepaint="+boundsToRepaint);
return boundsToRepaint;
}
@Override
public void stopDragging(DrawingController<?> controller, GraphicalRepresentation<?> focusedGR) {
if (drawEdge && currentDraggingLocationInDrawingView != null && isDnd) {
try {
GraphicalRepresentation<?> targetGR = controller.getGraphicalRepresentation(target);
if (targetGR == null) {
targetGR = controller.getDrawingGraphicalRepresentation();
}
SimplifiedCardinalDirection direction = FGEPoint.getSimplifiedOrientation(
new FGEPoint(roleGR.convertLocalNormalizedPointToRemoteViewCoordinates(this.normalizedStartPoint,
controller.getDrawingGraphicalRepresentation(), controller.getScale())), new FGEPoint(
currentDraggingLocationInDrawingView));
Point dropPoint = currentDraggingLocationInDrawingView;
if (dropPoint.x < 0) {
dropPoint.x = 0;
}
if (dropPoint.y < 0) {
dropPoint.y = 0;
}
Point p = GraphicalRepresentation.convertPoint(controller.getDrawingGraphicalRepresentation(), dropPoint, targetGR,
controller.getScale());
FGEPoint dropLocation = new FGEPoint(p.x / controller.getScale(), p.y / controller.getScale());
Role from = roleGR.getDrawable();
Role to = null;
switch (mode) {
case ROLE:
to = createRole(dropLocation, target, from, direction);
break;
case SPECIALIZATION:
if (this.to != null) {
to = this.to.getDrawable();
}
break;
default:
logger.warning("Not implemented !!!");
break;
}
if (to == null) {
return;
}
AddRoleSpecialization addRoleSpecializationAction = AddRoleSpecialization.actionType.makeNewAction(from, null,
((RoleEditorController) controller).getEditor());
addRoleSpecializationAction.setNewParentRole(to);
addRoleSpecializationAction.setRoleSpecializationAutomaticallyCreated(true);
addRoleSpecializationAction.doAction();
if (mode == Mode.ROLE) {
controller.setSelectedObject(controller.getGraphicalRepresentation(to));
}
} finally {
resetVariables();
((RoleEditorView) controller.getDrawingView()).resetFloatingPalette();
DrawingView<?> drawingView = controller.getDrawingView();
FGEPaintManager paintManager = drawingView.getPaintManager();
paintManager.invalidate(drawingView.getDrawingGraphicalRepresentation());
paintManager.repaint(drawingView.getDrawingGraphicalRepresentation());
}
} else {
resetVariables();
}
super.stopDragging(controller, focusedGR);
}
private void resetVariables() {
drawEdge = false;
isDnd = false;
to = null;
currentDraggingLocationInDrawingView = null;
}
private Role createRole(FGEPoint dropLocation, RoleList container, Role from, SimplifiedCardinalDirection direction) {
FGEPoint locationInDrawing = null;
if (controller.getGraphicalRepresentation(container) != null) {
locationInDrawing = dropLocation.transform(GraphicalRepresentation.convertCoordinatesAT(
controller.getGraphicalRepresentation(container), controller.getDrawingGraphicalRepresentation(), 1.0));// gr.getLocationInDrawing();
}
FlexoWorkflow workflow = container.getWorkflow();
AddRole addRole = AddRole.actionType.makeNewAction(workflow, null, controller.getWKFController().getEditor());
addRole.setLocation(dropLocation.x, dropLocation.y);
addRole.setNewRoleName(workflow.getRoleList().getNextNewUserRoleName());
addRole.setRoleToClone(from);
addRole.setRoleAutomaticallyCreated(true);
addRole.doAction();
if (addRole.getNewRole() != null) {
ShapeGraphicalRepresentation<?> gr = (ShapeGraphicalRepresentation<?>) controller.getGraphicalRepresentation(addRole
.getNewRole());
if (locationInDrawing == null) {
locationInDrawing = gr.getLocationInDrawing();
}
double xOffset = 0;
double yOffset = 0;
if (gr != null) {
if (gr.getBorder() != null) {
xOffset -= gr.getBorder().left;
yOffset -= gr.getBorder().top;
}
/*switch (direction) {
case NORTH:
xOffset-=gr.getWidth()/2;
yOffset-=gr.getHeight();
break;
case SOUTH:
xOffset-=gr.getWidth()/2;
break;
case WEST:
xOffset-=gr.getWidth();
yOffset-=gr.getHeight()/2;
break;
case EAST:
yOffset-=gr.getHeight()/2;
break;
default:
break;
}*/
xOffset -= gr.getWidth() / 2;
yOffset -= gr.getHeight() / 2;
if (xOffset < 0 && -xOffset > locationInDrawing.x) {
xOffset = -locationInDrawing.x;
}
if (yOffset < 0 && -yOffset > locationInDrawing.y) {
yOffset = -locationInDrawing.y;
}
gr.setX(gr.getX() + xOffset);
gr.setY(gr.getY() + yOffset);
}
}
return addRole.getNewRole();
}
@Override
public Rectangle paint(FGEGraphics drawingGraphics) {
// System.out.println("Focused:"+nodeGR.getIsFocused());
if (roleGR.getIsSelected() && !roleGR.getIsFocused()) {
return null;
}
if (/*nodeGR.getIsSelected() ||*/roleGR.isResizing() || roleGR.isMoving()) {
return null;
}
if (!roleGR.getDrawing().isEditable()) {
return null;
}
AffineTransform at = GraphicalRepresentation.convertNormalizedCoordinatesAT(roleGR, drawingGraphics.getGraphicalRepresentation());
Graphics2D oldGraphics = drawingGraphics.cloneGraphics();
drawingGraphics.setDefaultForeground(NONE);
drawingGraphics.setDefaultBackground(DEFAULT);
FGERoundRectangle paletteRect = (FGERoundRectangle) getArea().transform(at);
FGERoundRectangle nodeRect = (FGERoundRectangle) this.roleRect.transform(at);
FGERectangle edgeRect = (FGERectangle) this.edgeRect.transform(at);
double arrowSize = 4/** drawingGraphics.getScale() */
;
paletteRect.paint(drawingGraphics);
// 1. Node
drawingGraphics.setDefaultForeground(NODE_FOREGROUND);
drawingGraphics.setDefaultBackground(NODE_BACKGROUND);
nodeRect.paint(drawingGraphics);
// 2. Edge
drawingGraphics.setDefaultForeground(EDGE_FOREGROUND);
// drawingGraphics.setDefaultBackground(EDGE_BACKGROUND);
drawingGraphics.useDefaultForegroundStyle();
// drawingGraphics.useDefaultBackgroundStyle();
FGEPoint eastPt, westPt, northPt, southPt;
switch (orientation) {
case EAST:
eastPt = edgeRect.getEastPt();
westPt = edgeRect.getWestPt();
drawingGraphics.drawLine(westPt.x, westPt.y, eastPt.x - arrowSize, eastPt.y);
drawingGraphics.drawLine(eastPt.x - arrowSize, edgeRect.y + 1, eastPt.x - arrowSize, edgeRect.y + ELEMENTS_HEIGHT - 1);
drawingGraphics.drawLine(eastPt.x - arrowSize, edgeRect.y + 1, eastPt.x, eastPt.y);
drawingGraphics.drawLine(eastPt.x - arrowSize, edgeRect.y + ELEMENTS_HEIGHT - 1, eastPt.x, eastPt.y);
break;
case WEST:
eastPt = edgeRect.getEastPt();
westPt = edgeRect.getWestPt();
drawingGraphics.drawLine(eastPt.x, eastPt.y, edgeRect.x + arrowSize, eastPt.y);
drawingGraphics.drawLine(edgeRect.x + arrowSize, edgeRect.y + 1, edgeRect.x + arrowSize, edgeRect.y + ELEMENTS_HEIGHT - 1);
drawingGraphics.drawLine(edgeRect.x + arrowSize, edgeRect.y + 1, westPt.x, westPt.y);
drawingGraphics.drawLine(edgeRect.x + arrowSize, edgeRect.y + ELEMENTS_HEIGHT - 1, westPt.x, westPt.y);
break;
case NORTH:
northPt = edgeRect.getNorthPt();
southPt = edgeRect.getSouthPt();
drawingGraphics.drawLine(southPt.x, southPt.y, southPt.x, edgeRect.y + arrowSize);
drawingGraphics.drawLine(edgeRect.x + 2, edgeRect.y + arrowSize, edgeRect.x + ELEMENTS_WIDTH - 2, edgeRect.y + arrowSize);
drawingGraphics.drawLine(edgeRect.x + 2, edgeRect.y + arrowSize, northPt.x, northPt.y);
drawingGraphics.drawLine(edgeRect.x + ELEMENTS_WIDTH - 2, edgeRect.y + arrowSize, northPt.x, northPt.y);
break;
case SOUTH:
northPt = edgeRect.getNorthPt();
southPt = edgeRect.getSouthPt();
drawingGraphics.drawLine(northPt.x, northPt.y, northPt.x, southPt.y - arrowSize);
drawingGraphics.drawLine(edgeRect.x + 2, southPt.y - arrowSize, edgeRect.x + ELEMENTS_WIDTH - 2, southPt.y - arrowSize);
drawingGraphics.drawLine(edgeRect.x + 2, southPt.y - arrowSize, southPt.x, southPt.y);
drawingGraphics.drawLine(edgeRect.x + ELEMENTS_WIDTH - 2, southPt.y - arrowSize, southPt.x, southPt.y);
break;
default:
break;
}
drawingGraphics.releaseClonedGraphics(oldGraphics);
return drawingGraphics.getGraphicalRepresentation().convertNormalizedRectangleToViewCoordinates(paletteRect.getBoundingBox(),
drawingGraphics.getScale());
}
@Override
public boolean isClickable() {
return false;
}
@Override
public void update(Observable o, Object arg) {
if (o == roleGR) {
if (arg instanceof ObjectResized) {
updateElements(orientation);
}
}
}
private int PALETTE_WIDTH = 16;
private int PALETTE_HEIGHT = 2 * ELEMENTS_HEIGHT + 3 * SPACING;
private void updateElements(SimplifiedCardinalDirection orientation) {
setArea(makeRoundRect(roleGR, orientation));
AffineTransform at = AffineTransform.getScaleInstance(1 / roleGR.getWidth(), 1 / roleGR.getHeight());
if (orientation == SimplifiedCardinalDirection.EAST || orientation == SimplifiedCardinalDirection.WEST) {
PALETTE_WIDTH = ELEMENTS_WIDTH + 4;
PALETTE_HEIGHT = 2 * ELEMENTS_HEIGHT + 3 * SPACING;
} else if (orientation == SimplifiedCardinalDirection.NORTH || orientation == SimplifiedCardinalDirection.SOUTH) {
PALETTE_WIDTH = 2 * ELEMENTS_WIDTH + 3 * SPACING;
PALETTE_HEIGHT = ELEMENTS_HEIGHT + 4;
}
switch (orientation) {
case EAST:
roleRect = (FGERoundRectangle) new FGERoundRectangle(roleGR.getWidth() + SPACING + (PALETTE_WIDTH - ELEMENTS_WIDTH) / 2 + 0.5,
(roleGR.getHeight() - PALETTE_HEIGHT) / 2 + SPACING, ELEMENTS_WIDTH, ELEMENTS_HEIGHT, 2, 2, Filling.FILLED)
.transform(at);
edgeRect = (FGERectangle) new FGERectangle(roleGR.getWidth() + SPACING + (PALETTE_WIDTH - ELEMENTS_WIDTH) / 2,
(roleGR.getHeight() - PALETTE_HEIGHT) / 2 + SPACING + (SPACING + ELEMENTS_HEIGHT), ELEMENTS_WIDTH, ELEMENTS_HEIGHT,
Filling.FILLED).transform(at);
break;
case WEST:
roleRect = (FGERoundRectangle) new FGERoundRectangle(-SPACING - ELEMENTS_WIDTH, (roleGR.getHeight() - PALETTE_HEIGHT) / 2
+ SPACING, ELEMENTS_WIDTH, ELEMENTS_HEIGHT, 2, 2, Filling.FILLED).transform(at);
edgeRect = (FGERectangle) new FGERectangle(-SPACING - ELEMENTS_WIDTH, (roleGR.getHeight() - PALETTE_HEIGHT) / 2 + SPACING
+ (SPACING + ELEMENTS_HEIGHT), ELEMENTS_WIDTH, ELEMENTS_HEIGHT, Filling.FILLED).transform(at);
break;
case NORTH:
roleRect = (FGERoundRectangle) new FGERoundRectangle((roleGR.getWidth() - PALETTE_WIDTH) / 2 + SPACING, -SPACING
- ELEMENTS_HEIGHT, ELEMENTS_WIDTH, ELEMENTS_HEIGHT, 2, 2, Filling.FILLED).transform(at);
edgeRect = (FGERectangle) new FGERectangle((roleGR.getWidth() - PALETTE_WIDTH) / 2 + SPACING + (SPACING + ELEMENTS_WIDTH),
-SPACING - ELEMENTS_HEIGHT, ELEMENTS_WIDTH, ELEMENTS_HEIGHT, Filling.FILLED).transform(at);
break;
case SOUTH:
roleRect = (FGERoundRectangle) new FGERoundRectangle((roleGR.getWidth() - PALETTE_WIDTH) / 2 + SPACING, roleGR.getHeight()
+ SPACING + (PALETTE_HEIGHT - ELEMENTS_HEIGHT) / 2 + 0.5, ELEMENTS_WIDTH, ELEMENTS_HEIGHT, 2, 2, Filling.FILLED)
.transform(at);
edgeRect = (FGERectangle) new FGERectangle((roleGR.getWidth() - PALETTE_WIDTH) / 2 + SPACING + (SPACING + ELEMENTS_WIDTH),
roleGR.getHeight() + SPACING + (PALETTE_HEIGHT - ELEMENTS_HEIGHT) / 2 + 0.5, ELEMENTS_WIDTH, ELEMENTS_HEIGHT,
Filling.FILLED).transform(at);
break;
default:
break;
}
}
private static FGERoundRectangle makeRoundRect(RoleGR roleGR, SimplifiedCardinalDirection orientation) {
double x, y, width, height;
int PALETTE_WIDTH = 0, PALETTE_HEIGHT = 0;
if (orientation == SimplifiedCardinalDirection.EAST || orientation == SimplifiedCardinalDirection.WEST) {
PALETTE_WIDTH = ELEMENTS_WIDTH + 4;
PALETTE_HEIGHT = 2 * ELEMENTS_HEIGHT + 3 * SPACING;
} else if (orientation == SimplifiedCardinalDirection.NORTH || orientation == SimplifiedCardinalDirection.SOUTH) {
PALETTE_WIDTH = 2 * ELEMENTS_WIDTH + 3 * SPACING;
PALETTE_HEIGHT = ELEMENTS_HEIGHT + 4;
}
switch (orientation) {
case EAST:
x = roleGR.getWidth() + SPACING;
y = (roleGR.getHeight() - PALETTE_HEIGHT) / 2;
width = PALETTE_WIDTH;
height = PALETTE_HEIGHT;
return new FGERoundRectangle(x / roleGR.getWidth(), y / roleGR.getHeight(), width / roleGR.getWidth(), height
/ roleGR.getHeight(), 13.0 / roleGR.getWidth(), 13.0 / roleGR.getHeight(), Filling.FILLED);
case WEST:
x = -SPACING - ELEMENTS_WIDTH;
y = (roleGR.getHeight() - PALETTE_HEIGHT) / 2;
width = PALETTE_WIDTH;
height = PALETTE_HEIGHT;
return new FGERoundRectangle(x / roleGR.getWidth(), y / roleGR.getHeight(), width / roleGR.getWidth(), height
/ roleGR.getHeight(), 13.0 / roleGR.getWidth(), 13.0 / roleGR.getHeight(), Filling.FILLED);
case NORTH:
x = (roleGR.getWidth() - PALETTE_WIDTH) / 2;
y = -SPACING - ELEMENTS_HEIGHT;
width = PALETTE_WIDTH;
height = PALETTE_HEIGHT;
return new FGERoundRectangle(x / roleGR.getWidth(), y / roleGR.getHeight(), width / roleGR.getWidth(), height
/ roleGR.getHeight(), 13.0 / roleGR.getWidth(), 13.0 / roleGR.getHeight(), Filling.FILLED);
case SOUTH:
x = (roleGR.getWidth() - PALETTE_WIDTH) / 2;
y = roleGR.getHeight() + SPACING;
width = PALETTE_WIDTH;
height = PALETTE_HEIGHT;
return new FGERoundRectangle(x / roleGR.getWidth(), y / roleGR.getHeight(), width / roleGR.getWidth(), height
/ roleGR.getHeight(), 13.0 / roleGR.getWidth(), 13.0 / roleGR.getHeight(), Filling.FILLED);
default:
return null;
}
}
}