org.sikuli.guide.Visual Maven / Gradle / Ivy
/*
* Copyright (c) 2010-2016, Sikuli.org, sikulix.com
* Released under the MIT License.
*
*/
/**
*
*/
package org.sikuli.guide;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.swing.JComponent;
import org.sikuli.basics.Debug;
import org.sikuli.script.Pattern;
import org.sikuli.script.Region;
public class Visual extends JComponent
implements Cloneable {
public enum Layout {
TOP,
BOTTOM,
LEFT,
RIGHT,
FOLLOWERS,
INSIDE,
OVER,
ORIGIN,
CENTER,
AROUND
};
public boolean hasChanged = false;
public int PADDING_X = 4;
public int PADDING_Y = 4;
//
Region targetRegion = null;
Visual targetComponent = null;
Pattern targetPattern = null;
Guide currentGuide = null;
public void setGuide(Guide g) {
currentGuide = g;
}
public Region getTarget() {
if (targetRegion != null) {
return targetRegion;
}
return getRegion();
}
public Visual setScale(float scale) {
return this;
}
public Layout layout = Layout.OVER;
public Layout currentLayout = layout;
public Visual setLayout(Layout lo) {
currentLayout = layout;
layout = lo;
setLocationRelative(lo);
updateComponent();
return this;
}
public static Color defColor = Color.RED;
Color color;
public static Color defColorFront = Color.MAGENTA;
Color colorFront;
public static Color defColorBack = Color.WHITE;
Color colorBack;
public static Color defColorFrame = Color.BLACK;
Color colorFrame;
public static Color defColorText = Color.BLACK;
Color colorText;
/**
* set a Java Color for the component
* not all components have all color options
* @param all sets the color for all options (which have to be null in this case)
* @param front sets the foreground color
* @param back sets the background color
* @param frame sets the color of the frame
* @param text sets the color of the text
* @return the component itself for dot-chaining
*/
public Visual setColors(Color all, Color front, Color back, Color frame, Color text) {
if (all != null) {
color = all;
}
if (front != null) {
colorFront = front;
setForeground(colorFront);
}
if (back != null) {
colorBack = back;
setBackground(colorBack);
}
if (frame != null) {
colorFrame = frame;
}
if (text != null) {
colorText = text;
}
updateComponent();
return this;
}
/**
* mainly for Jython layer: colors given as (r, g, b) integer array
*
* @param front sets the foreground color
* @param back sets the background color
* @param frame sets the color of the frame
* @param text sets the color of the text
* @return the component itself for dot-chaining
*/
public Visual setColors(int[] front, int[] back, int[] frame, int[] text) {
Color cf = null;
Color cb = null;
Color cr = null;
Color ct = null;
if (front != null) {
cf = new Color(front[0], front[1], front[2]);
}
if (back != null) {
cb = new Color(back[0], back[1], back[2]);
}
if (frame != null) {
cr = new Color(frame[0], frame[1], frame[2]);
}
if (text != null) {
ct = new Color(text[0], text[1], text[2]);
}
setColors(null, cf, cb, cr, ct);
updateComponent();
return this;
}
/**
* set the front and back color
* @param color
* @return the component itself
*/
public Visual setColor(Color color) {
setColors(null, color, color, null, null);
return this;
}
/**
* set the front and back color as (r, g, b) integer array
* @return the component itself
*/
public Visual setColor(int r, int g, int b) {
setColor(new Color(r, g, b));
return this;
}
/**
* set the text color
* @param color
* @return the component itself
*/
public Visual setTextColor(Color color) {
setColors(null, null, null, null, color);
return this;
}
/**
* set text color as (r, g, b) integer array
* @return the component itself
*/
public Visual setTextColor(int r, int g, int b) {
setTextColor(new Color(r, g, b));
return this;
}
public static String getColorHex(Color col) {
String rgb = Integer.toHexString(col.getRGB());
return rgb.substring(2, rgb.length()).toUpperCase();
}
public static int defStroke = 3;
int stroke;
public Visual setStroke(int stk) {
stroke = stk;
return this;
}
public static String defFont = "";
String fontName = "";
public static int defFontSize = 0;
int fontSize = 0;
public Visual setFont(String font, int fontSize) {
if (font != null && !this.fontName.isEmpty()) {
this.fontName = font;
hasChanged = true;
}
if (fontSize > 0 && this.fontSize > 0) {
this.fontSize = fontSize;
hasChanged = true;
}
if (hasChanged) {
hasChanged = false;
updateComponent();
}
return this;
}
public Visual setFontSize(int i) {
setFont(null, i);
return this;
}
String getStyleString() {
String s = "font-size:" + fontSize + "px;color:#" + getColorHex(colorText)
+ ";background-color:#" + getColorHex(colorBack) + ";padding:3px";
if (!fontName.isEmpty()) {
s = "font:" + fontName + ";" + s;
}
return s;
}
static int defMaxWidth = 300;
int maxWidth;
public Visual setMaxWidth(int w) {
maxWidth = w;
return this;
}
String text = "";
public String getText() {
return text;
}
public Visual setText(String text) {
if (!this.text.isEmpty()) {
this.text = text;
updateComponent();
}
return this;
}
//
public Visual() {
super();
init();
}
private void init() {
cm = new ComponentMover();
setMovable(false);
setActualLocation(0, 0);
setActualSize(new Dimension(0, 0));
color = defColor;
colorFront = defColorFront;
colorBack = defColorBack;
colorFrame = defColorFrame;
colorText = defColorText;
stroke = defStroke;
fontName = defFont;
fontSize = defFontSize;
maxWidth = defMaxWidth;
}
//
private boolean autoLayoutEnabled = false;
private boolean autoResizeEnabled = false;
private boolean autoMoveEnabled = false;
private boolean autoVisibilityEnabled = false;
public void setAutoLayoutEnabled(boolean autoLayoutEnabled) {
this.autoLayoutEnabled = autoLayoutEnabled;
}
public boolean isAutoLayoutEnabled() {
return autoLayoutEnabled;
}
public void setAutoResizeEnabled(boolean autoResizeEnabled) {
this.autoResizeEnabled = autoResizeEnabled;
}
public boolean isAutoResizeEnabled() {
return autoResizeEnabled;
}
public void setAutoMoveEnabled(boolean autoMoveEnabled) {
this.autoMoveEnabled = autoMoveEnabled;
}
public boolean isAutoMoveEnabled() {
return autoMoveEnabled;
}
public void setAutoVisibilityEnabled(boolean autoVisibilityEnabled) {
this.autoVisibilityEnabled = autoVisibilityEnabled;
}
public boolean isAutoVisibilityEnabled() {
return autoVisibilityEnabled;
}
//
//
private Rectangle actualBounds = new Rectangle();
public Rectangle getActualBounds() {
return actualBounds;
}
public Region getRegion() {
return Region.create(getBounds());
}
public void setActualBounds(Rectangle actualBounds) {
this.actualBounds = (Rectangle) actualBounds.clone();
Rectangle paintBounds = (Rectangle) actualBounds.clone();
if (hasShadow()) {
paintBounds.x -= (shadowSize - shadowOffset);
paintBounds.y -= (shadowSize - shadowOffset);
paintBounds.width += (2 * shadowSize);
paintBounds.height += (2 * shadowSize);
}
super.setBounds(paintBounds);
updateAllFollowers();
}
public Point getCenter() {
Point loc = new Point(getActualLocation());
Dimension size = getActualSize();
loc.x += size.width / 2;
loc.y += size.height / 2;
return loc;
}
public Dimension getActualSize() {
return new Dimension(getActualWidth(), getActualHeight());
}
public void setActualSize(int width, int height) {
if (height == 0) {
setActualSize(new Dimension(width, getActualHeight()));
} else if (width == 0) {
setActualSize(new Dimension(getActualWidth(), height));
} else {
setActualSize(new Dimension(width, height));
}
}
public void setActualSize(Dimension actualSize) {
actualBounds.setSize(actualSize);
Dimension paintSize = (Dimension) actualSize.clone();
if (hasShadow()) {
paintSize.width += (2 * shadowSize);
paintSize.height += (2 * shadowSize);
}
super.setSize(paintSize);
updateAllFollowers();
}
public int getActualWidth() {
return getActualBounds().width;
}
public int getActualHeight() {
return getActualBounds().height;
}
public Point getActualLocation() {
return actualBounds.getLocation();
}
public void offsetLocation(int x, int y) {
setActualLocation(getActualLocation().x + x, getActualLocation().y + y);
}
public void setActualLocation(Point location) {
setActualLocation(location.x, location.y);
}
public void setActualLocation(int x, int y) {
int paintX = x;
int paintY = y;
actualBounds.setLocation(x, y);
if (hasShadow()) {
paintX -= (shadowSize - shadowOffset);
paintY -= (shadowSize - shadowOffset);
}
super.setLocation(paintX, paintY);
updateAllFollowers();
}
class Margin {
int top;
int left;
int bottom;
int right;
}
Margin margin = null;
public void setMargin(int top, int left, int bottom, int right) {
margin = new Margin();
margin.top = top;
margin.left = left;
margin.bottom = bottom;
margin.right = right;
}
int offsetx = 0;
int offsety = 0;
public void setOffset(int offsetx, int offsety) {
this.offsetx = offsetx;
this.offsety = offsety;
offsetLocation(offsetx, offsety);
}
// TODO: fix this
float zoomLevel = 1.0f;
public void setZoomLevel(float zoomLevel) {
if (true) {
return;
}
this.zoomLevel = zoomLevel;
for (Visual sklComp : getFollowers()) {
if (sklComp.autolayout != null) {
sklComp.setZoomLevel(zoomLevel);
}
}
Debug.info("[setZoomLevel] Component:" + this);
// Debug.info("Actual bounds:" + actualBounds);
Rectangle bounds = new Rectangle(getActualBounds());
bounds.x *= zoomLevel;
bounds.y *= zoomLevel;
bounds.width *= zoomLevel;
bounds.height *= zoomLevel;
//super.setBounds(bounds);
super.setBounds(bounds);
for (Visual sklComp : getFollowers()) {
if (sklComp.autolayout != null) {
Debug.info("Updaing by offset:" + sklComp.autolayout);
Debug.info("Updaing child:" + sklComp);
if (sklComp.autolayout instanceof AutoLayoutByMovement) {
((AutoLayoutByMovement) sklComp.autolayout).x = bounds.x;
((AutoLayoutByMovement) sklComp.autolayout).y = bounds.y;
} else if (sklComp.autolayout instanceof AutoLayoutByOffset) {
// ((AutoLayoutByOffset) sklComp.autolayout).offsetx *= zoomLevel;
// ((AutoLayoutByOffset) sklComp.autolayout).offsety *= zoomLevel;
// sklComp.zoomLevel = zoomLevel;
sklComp.autolayout.update();
} else {
sklComp.autolayout.update();
}
}
}
}
// this allows the component to be dragged to another location on the screen
ComponentMover cm;
public void setMovable(boolean movable) {
if (movable) {
cm.registerComponent(this);
} else {
cm.deregisterComponent(this);
}
}
float opacity = 1.0f;
//
//
public void setOpacity(float opacity) {
if (opacity > 0) {
setVisible(true);
} else {
setVisible(false);
}
this.opacity = opacity;
for (Visual sklComp : getFollowers()) {
sklComp.setOpacity(opacity);
}
// if (shadowRenderer != null){
// shadowRenderer.createShadowImage();
// }
Rectangle r = getBounds();
if (getTopLevelAncestor() != null) //getTopLevelAncestor().repaint(r.x,r.y,r.width,r.height);
// for some reason the whole thing needs to be repainted otherwise the
// shadow of other compoments looks weird
{
getTopLevelAncestor().repaint();
}
// public void changeOpacityTo(float targetOpacity){
// OpacityAnimator anim = new OpacityAnimator(this, opacity,targetOpacity);
// anim.start();
// }
}
public void updateComponent() {
}
public void paintPlain(Graphics g) {
super.paint(g);
}
@Override
public void paint(Graphics g) {
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
if (shadowRenderer != null) {
shadowRenderer.paintComponent(g2);
g2.translate((shadowSize - shadowOffset), (shadowSize - shadowOffset));
}
super.paint(g2);
Graphics2D g2d = (Graphics2D) g;
((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
g2d.drawImage(image, 0, 0, null, null);
}
//
//
ShadowRenderer shadowRenderer;
private int defShadowSize = 10;
int shadowSize = 0;
private int defShadowOffset = 2;
int shadowOffset = 0;
public void setShadowDefault() {
setShadow(defShadowSize, defShadowOffset);
}
public void setShadow(int shadowSize, int shadowOffset) {
this.shadowSize = shadowSize;
this.shadowOffset = shadowOffset;
shadowRenderer = new ShadowRenderer(this, shadowSize);
super.setSize(getActualWidth() + 2 * shadowSize, getActualHeight() + 2 * shadowSize);
Point p = getActualLocation();
p.x = p.x - shadowSize + shadowOffset;
p.y = p.y - shadowSize + shadowOffset;
super.setLocation(p.x, p.y);
}
boolean hasShadow() {
return shadowRenderer != null;
}
//
//
boolean animationRunning = false;
class AnimationSequence {
Queue queue = new LinkedBlockingQueue();
private void startNextAnimation() {
if (queue.peek() != null) {
NewAnimator anim = queue.remove();
anim.start();
anim.setListener(new AnimationListener() {
@Override
public void animationCompleted() {
startNextAnimation();
}
});
}
}
public void add(NewAnimator animator) {
queue.add(animator);
}
public void start() {
startNextAnimation();
}
}
AnimationSequence animationSequence = new AnimationSequence();
AnimationFactory getAnimationFactory() {
return new AnimationFactory();
}
public void addAnimation(NewAnimator anim) {
animationSequence.add(anim);
}
public void addMoveAnimation(Point source, Point destination) {
animationSequence.add(AnimationFactory.createMoveAnimation(this, source, destination));
}
public void addResizeAnimation(Dimension currentSize, Dimension targetSize) {
animationSequence.add(AnimationFactory.createResizeAnimation(this, currentSize, targetSize));
}
public void addCircleAnimation(Point origin, float radius) {
animationSequence.add(AnimationFactory.createCircleAnimation(this, origin, radius));
}
public void addFadeinAnimation() {
if (opacity < 1f) {
animationSequence.add(AnimationFactory.createOpacityAnimation(this, opacity, 1f));
}
}
public void addFadeoutAnimation() {
if (opacity > 0f) {
animationSequence.add(AnimationFactory.createOpacityAnimation(this, opacity, 0f));
}
}
public void addSlideAnimation(Point destination, Layout side) {
Point p0 = new Point(destination);
Point p1 = new Point(destination);
if (side == Layout.RIGHT) {
p0.x += 20;
} else if (side == Layout.BOTTOM) {
p0.y += 20;
} else if (side == Layout.TOP) {
p0.y -= 20;
} else if (side == Layout.LEFT) {
p0.x -= 20;
}
setActualLocation(p0);
addMoveAnimation(p0, p1);
}
public void startAnimation() {
animationSequence.start();
}
public void stopAnimation() {
if (emphasis_anim != null) {
emphasis_anim.stop();
}
if (entrance_anim != null) {
entrance_anim.stop();
}
}
public Animator createSlidingAnimator(int offset_x, int offset_y) {
Point dest = getActualLocation();
Point src = new Point(dest.x + offset_x, dest.y + offset_y);
return new MoveAnimator(this, src, dest);
}
public Animator createMoveAnimator(int dest_x, int dest_y) {
Point src = getActualLocation();
Point dest = new Point(dest_x, dest_y);
return new MoveAnimator(this, src, dest);
}
public void resizeTo(Dimension targetSize) {
//ResizeAnimator anim = new ResizeAnimator(this, getActualSize(),targetSize);
//anim.start();
}
public void moveTo(Point targetLocation) {
NewAnimator anim = AnimationFactory.createCenteredMoveAnimation(this, getActualLocation(), targetLocation);
anim.start();
}
public void moveTo(Point targetLocation, AnimationListener listener) {
NewAnimator anim = AnimationFactory.createCenteredMoveAnimation(this, getActualLocation(), targetLocation);
anim.setListener(listener);
anim.start();
}
public void popin() {
Dimension targetSize = new Dimension(getActualSize());
targetSize.width /= 1.2;
targetSize.height /= 1.2;
NewAnimator anim = AnimationFactory.createCenteredResizeToAnimation(this, targetSize);
anim.start();
}
public void popout() {
setShadowDefault();
Dimension targetSize = new Dimension(getActualSize());
targetSize.width *= 1.2;
targetSize.height *= 1.2;
NewAnimator anim = AnimationFactory.createCenteredResizeToAnimation(this, targetSize);
anim.start();
}
Animator entrance_anim;
Animator emphasis_anim;
public void setEntranceAnimation(Animator anim) {
if (entrance_anim != null) {
entrance_anim.stop();
} else {
entrance_anim = anim;
}
}
public void setEmphasisAnimation(Animator anim) {
if (emphasis_anim != null) {
emphasis_anim.stop();
}
if (entrance_anim != null) {
entrance_anim.stop();
}
emphasis_anim = anim;
}
AnimationListener animationListener;
public void addAnimationListener(AnimationListener listener) {
animationListener = listener;
}
public void animationCompleted() {
if (animationListener != null) {
animationListener.animationCompleted();
}
}
//
//
public Visual left() {
left(0);
return this;
}
public Visual left(int x) {
setLayout(Layout.LEFT);
if (x != 0) {
setOffset(-x, 0);
}
return this;
}
public Visual right() {
return right(0);
}
public Visual right(int x) {
setLayout(Layout.RIGHT);
if (x != 0) {
setOffset(x, 0);
}
return this;
}
public Visual above() {
return above(0);
}
public Visual above(int y) {
setLayout(Layout.TOP);
if (y != 0) {
setOffset(0, -y);
}
return this;
}
public Visual below() {
return below(0);
}
public Visual below(int y) {
setLayout(Layout.BOTTOM);
if (y != 0) {
setOffset(0, y);
}
return this;
}
//
//
AutoLayout autolayout = null;
class AutoLayout implements ComponentListener {
private Visual targetComponent;
AutoLayout(Visual targetComponent) {
this.setTargetComponent(targetComponent);
//targetComponent.addComponentListener(this);
}
public void setTargetComponent(Visual targetComponent) {
this.targetComponent = targetComponent;
}
public Visual getTargetComponent() {
return targetComponent;
}
void update() {
//Debug.info("Update caused by leader:" + this);
// TODO calculate necesary region to udpate
// if (getParent()!=null){
//
// if (getParent().getParent()!=null){
// getParent().getParent().repaint();
// }else{
// getParent().repaint();
// }
// }
}
void stop() {
// targetComponent.removeComponentListener(this);
}
@Override
public void componentHidden(ComponentEvent e) {
// if (isAutoVisibilityEnabled()){
// setVisible(false);
// update();
// }
}
@Override
public void componentMoved(ComponentEvent e) {
// if (isAutoMoveEnabled())
// update();
}
@Override
public void componentResized(ComponentEvent e) {
// if (isAutoResizeEnabled())
// update();
}
@Override
public void componentShown(ComponentEvent e) {
// if (isAutoVisibilityEnabled()){
// setVisible(true);
// update();
// }
}
}
class AutoLayoutBySide extends AutoLayout {
Layout side;
AutoLayoutBySide(Visual targetComponent, Layout side) {
super(targetComponent);
this.side = side;
}
@Override
void update() {
if (side == Layout.FOLLOWERS) {
// set to the total bounds of the other followers
// first set its bounds to be equal to the targets, so that
// its current bounds won't have effect on the calculation
// of the total bounds
setBounds(getTargetComponent().getBounds());
// then this call will gives us the total bounds of the
// rest of the followers
Rectangle totalBounds = getTargetComponent().getFollowerBounds();
totalBounds.grow(5, 5);
setBounds(totalBounds);
} else {
setLocationRelativeToRegion(getTargetComponent().getRegion(), side);
}
super.update();
}
}
class AutoLayoutByMovement extends AutoLayout {
// previous known location of the target this component follows
int x;
int y;
Point targetLocation;
AutoLayoutByMovement(Visual targetComponent) {
super(targetComponent);
targetLocation = new Point(targetComponent.getActualLocation());
this.x = targetComponent.getX();
this.y = targetComponent.getY();
}
@Override
public void update() {
//Debug.info("auto moved by leader");
Point newTargetLocation = getTargetComponent().getActualLocation();
int dx = newTargetLocation.x - targetLocation.x;
int dy = newTargetLocation.y - targetLocation.y;
targetLocation = newTargetLocation;
Point actualLocation = getActualLocation();
actualLocation.x += dx;
actualLocation.y += dy;
setActualLocation(actualLocation.x, actualLocation.y);
}
}
class AutoLayoutByOffset extends AutoLayout {
int offsetx;
int offsety;
AutoLayoutByOffset(Visual targetComponent, int offsetx, int offsety) {
super(targetComponent);
this.offsetx = offsetx;
this.offsety = offsety;
}
@Override
void update() {
setOffset(offsetx, offsety);
Region region = new Region(leader.getBounds());
setLocationRelativeToRegion(region, Layout.ORIGIN);
super.update();
}
}
class AutoLayoutByRatio extends AutoLayout {
float x, y;
AutoLayoutByRatio(Visual targetComponent, float x, float y) {
super(targetComponent);
this.x = x;
this.y = y;
}
@Override
void update() {
Region region = new Region(getTargetComponent().getBounds());
setHorizontalAlignmentWithRegion(region, x);
setVerticalAlignmentWithRegion(region, y);
super.update();
}
}
//
//
public Visual setTarget(RCPS target) {
if (target instanceof Region) {
targetRegion = (Region) target;
} else if (target instanceof Visual) {
targetComponent = (Visual) target;
} else if (target instanceof Pattern) {
targetPattern = (Pattern) target;
} else if (target instanceof String) {
targetPattern = new Pattern((String) target);
}
if (targetPattern != null) {
targetComponent = new SxAnchor(targetPattern);
currentGuide.addToFront(targetComponent);
setLayout(layout);
}
updateComponent();
return this;
}
public Visual setLocationRelative(Layout side) {
if (targetRegion != null) {
setLocationRelativeToRegion(targetRegion, side);
} else if (targetComponent != null) {
setLocationRelativeToComponent(targetComponent, side);
}
return this;
}
public void setLocationRelativeToComponent(Visual comp, Layout side) {
if (autolayout != null) {
autolayout.stop();
}
comp.addFollower(this);
autolayout = new AutoLayoutBySide(comp, side);
autolayout.update();
}
public void setLocationRelativeToComponent(Visual comp, int offsetx, int offsety) {
if (autolayout != null) {
autolayout.stop();
}
comp.addFollower(this);
autolayout = new AutoLayoutByOffset(comp, offsetx, offsety);
autolayout.update();
}
public void setLocationRelativeToComponent(Visual comp, float relativeX, float relativeY) {
if (autolayout != null) {
autolayout.stop();
}
autolayout = new AutoLayoutByRatio(comp, relativeX, relativeY);
autolayout.update();
}
public void setLocationRelativeToComponent(Visual leader) {
if (autolayout != null) {
autolayout.stop();
}
leader.addFollower(this);
autolayout = new AutoLayoutByMovement(leader);
autolayout.update();
}
public void setLocationRelativeToPoint(Point point, Layout side) {
Rectangle bounds = getActualBounds();
// TODO implement other positioning parameters
if (side == Layout.CENTER) {
setActualLocation(point.x - bounds.width / 2, point.y - bounds.height / 2);
}
}
public Visual setLocationRelativeToRegion(Region region, Layout side) {
if (margin != null) {
Region rectWithSpacing = new Region(region);
rectWithSpacing.x -= margin.left;
rectWithSpacing.y -= margin.top;
rectWithSpacing.w += (margin.left + margin.right);
rectWithSpacing.h += (margin.top + margin.bottom);
region = rectWithSpacing;
}
region.x += offsetx;
region.y += offsety;
targetRegion = region;
layout = side;
int height = getActualHeight();
int width = getActualWidth();
if (side == Layout.TOP) {
setActualLocation(region.x + region.w / 2 - width / 2, region.y - height);
} else if (side == Layout.BOTTOM) {
setActualLocation(region.x + region.w / 2 - width / 2, region.y + region.h);
} else if (side == Layout.LEFT) {
setActualLocation(region.x - width, region.y + region.h / 2 - height / 2);
} else if (side == Layout.RIGHT) {
setActualLocation(region.x + region.w, region.y + region.h / 2 - height / 2);
} else if (side == Layout.INSIDE) {
setActualLocation(region.x + region.w / 2 - width / 2, region.y + region.h / 2 - height / 2);
} else if (side == Layout.OVER) {
setActualBounds(region.getRect());
} else if (side == Layout.ORIGIN) {
setActualLocation(region.x, region.y);
}
return this;
}
public void setHorizontalAlignmentWithRegion(Region region, float f) {
int x0 = region.x;
int x1 = region.x + region.w - getActualWidth();
int x = (int) (x0 + (x1 - x0) * f);
setActualLocation(x, getActualLocation().y);
}
public void setVerticalAlignmentWithRegion(Region region, float f) {
int y0 = region.y;
int y1 = region.y + region.h - getActualHeight();
int y = (int) (y0 + (y1 - y0) * f);
setActualLocation(getActualLocation().x, y);
}
//
//
private ArrayList followers = new ArrayList();
Visual leader;
public void removeFromLeader() {
if (leader != null) {
leader.removeFollower(this);
}
leader = null;
}
public void addFollower(Visual sklComp) {
// force the follower to have the same visibility
sklComp.setVisible(isVisible());
sklComp.setOpacity(opacity);
if (followers.indexOf(sklComp) < 0) {
// if this component is not already a follower
// add it to the list of follower
followers.add(sklComp);
// remove its previous leader
sklComp.removeFromLeader();
// set its new leader to self
sklComp.leader = this;
}
}
private void updateAllFollowers() {
for (Visual sklComp : getFollowers()) {
if (sklComp.autolayout != null) {
sklComp.autolayout.update();
}
}
}
@Override
public void setVisible(boolean visible) {
for (Visual follower : getFollowers()) {
follower.setVisible(visible);
}
super.setVisible(visible);
}
//
// @Override
// public void setLocation(Point location){
// setLocation(location.x, location.y);
// }
// @Override
// public void setLocation(int x, int y){
//
//// if (shadowRenderer != null){
//// x -= 8;
//// y -= 8;
//// }
//
// getActualBounds().x = (int) (x/zoomLevel);
// getActualBounds().y = (int) (y/zoomLevel);
//
// super.setLocation(x,y);
// updateAllFollowers();
// }
//
// @Override
// public void setBounds(int x, int y, int w, int h){
//
// Rectangle bounds = new Rectangle(x,y,w,h);
//
// actualBounds = new Rectangle(bounds);
// actualBounds.x /= zoomLevel;
// actualBounds.y /= zoomLevel;
// actualBounds.width /= zoomLevel;
// actualBounds.height /= zoomLevel;
//
// for (Visual sklComp : getFollowers()){
// if (sklComp.autolayout != null){
// sklComp.autolayout.update();
// }
// }
// super.setBounds(x,y,w,h);
// }
// @Override
// public void setBounds(Rectangle bounds){
//
// setActualBounds(new Rectangle(bounds));
// getActualBounds().x /= zoomLevel;
// getActualBounds().y /= zoomLevel;
// getActualBounds().width /= zoomLevel;
// getActualBounds().height /= zoomLevel;
//
// super.setBounds(bounds);
// updateAllFollowers();
// }
// @Override
// public void setSize(int width, int height){
// getActualBounds().width = (int) (width/zoomLevel);
// getActualBounds().height = (int) (height/zoomLevel);
//
// if (hasShadow()){
// width += 20;
// height += 20;
// }
//
// super.setSize(width, height);
//// updateAllFollowers();
// }
//
// @Override
// public void setSize(Dimension size){
//// getActualBounds().width = (int) (size.width/zoomLevel);
//// getActualBounds().height = (int) (size.height/zoomLevel);
//
//// if (hasShadow()){
//// size.width += 20;
//// size.height += 20;
//// }
//
// super.setSize(size);
//// updateAllFollowers();
// }
//
public ArrayList getFollowers() {
return followers;
}
public Visual getLeader() {
return leader;
}
public void removeFollower(Visual comp) {
followers.remove(comp);
}
public Rectangle getFollowerBounds() {
// find the total bounds of all the components
Rectangle bounds = new Rectangle(getBounds());
for (Visual sklComp : getFollowers()) {
bounds.add(sklComp.getBounds());
}
return bounds;
}
//
public void removeFrom(Container container) {
for (Visual follower : getFollowers()) {
follower.removeFrom(container);
}
container.remove(this);
}
@Override
public String toString() {
return "" + getClass() + " " + "[actualBounds=" + getActualBounds() + "]";
}
@Override
public Object clone() {
Visual clone;
try {
clone = (Visual) super.clone();
// do not clone references to other components
clone.followers = new ArrayList();
clone.removeFromLeader();
clone.actualBounds = new Rectangle(actualBounds);
clone.autolayout = null;
//clone.connectors = new ArrayList();
return clone;
} catch (CloneNotSupportedException e) {
throw new InternalError(e.toString());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy