001: package net.xoetrope.builder.editor;
002:
003: import java.util.Vector;
004:
005: import java.awt.Color;
006: import java.awt.Component;
007: import java.awt.Container;
008: import java.awt.Cursor;
009: import java.awt.Dimension;
010: import java.awt.Label;
011: import java.awt.Point;
012: import java.awt.Rectangle;
013: import java.awt.event.FocusEvent;
014: import java.awt.event.FocusListener;
015: import java.awt.event.MouseEvent;
016: import java.awt.event.MouseListener;
017: import java.awt.event.MouseMotionListener;
018: import javax.swing.BorderFactory;
019: import javax.swing.JFrame;
020: import javax.swing.JLabel;
021: import javax.swing.JPopupMenu;
022: import javax.swing.SwingUtilities;
023:
024: import net.xoetrope.builder.editor.components.ComponentHelper;
025: import net.xoetrope.builder.editor.components.PropertyHelper;
026: import net.xoetrope.builder.editor.events.SizerListener;
027: import net.xoetrope.xui.XPage;
028: import net.xoetrope.builder.editor.components.swing.GlassPanel;
029:
030: /**
031: * Provides a set of grab handles to visually manipulate a component. In response
032: * to grabbing one of the handles the component is resize or moved as needed.
033: * <p>Copyright (c) Xoetrope Ltd., 1998-2003</p>
034: * @version $Revision: 1.19 $
035: */
036: public class XComponentSizer extends JLabel implements MouseListener,
037: MouseMotionListener, FocusListener {
038: private static final int handleSize = 5;
039: private Component lN, lS, lE, lW, lSE, lSW, lNE, lNW, moveHandle;
040: private Component target;
041: private Component currentHandle;
042: private Point startPoint;
043: private SizerListener sizerListener;
044: private XPageResource ownerPage;
045: private XGuidePane ownerScreen;
046: private XEditorProject currentProject;
047:
048: public XComponentSizer(XEditorProject project) {
049: currentProject = project;
050: setBounds(-100, -200, 1, 1);
051: setVisible(true);
052: setOpaque(false);
053: setBorder(BorderFactory.createLineBorder(new Color(192, 192,
054: 192, 128)));
055: addMouseListener(this );
056: addMouseMotionListener(this );
057: // enableEvents( AWTEvent.KEY_EVENT_MASK );
058: addFocusListener(this );
059: }
060:
061: /**
062: * Add a listener for the size changes
063: * @param sListener
064: */
065: public void setSizerListener(SizerListener sListener) {
066: sizerListener = sListener;
067: }
068:
069: /**
070: * Setup the grab handles for the component
071: */
072: private void setupHandles() {
073: lNW = createHandle(new Cursor(Cursor.NW_RESIZE_CURSOR));
074: lNW.setLocation(0, 0);
075: lSE = createHandle(new Cursor(Cursor.SE_RESIZE_CURSOR));
076: lE = createHandle(new Cursor(Cursor.E_RESIZE_CURSOR));
077: lS = createHandle(new Cursor(Cursor.S_RESIZE_CURSOR));
078: lN = createHandle(new Cursor(Cursor.N_RESIZE_CURSOR));
079: lW = createHandle(new Cursor(Cursor.W_RESIZE_CURSOR));
080: lNE = createHandle(new Cursor(Cursor.NE_RESIZE_CURSOR));
081: lSW = createHandle(new Cursor(Cursor.SW_RESIZE_CURSOR));
082: if (!(target instanceof javax.swing.JComponent || target instanceof XPage))
083: moveHandle = createHandle(new Cursor(Cursor.MOVE_CURSOR));
084: }
085:
086: /**
087: * Create a grab handle with a cursor to show its directionality
088: * @param cursor
089: * @return
090: */
091: private Component createHandle(Cursor cursor) {
092: Component handle;
093: if (target instanceof javax.swing.JComponent
094: || target instanceof XPage) {
095: handle = new JLabel();
096: ((JLabel) handle).setOpaque(true);
097: } else
098: handle = new Label();
099: handle.setBackground(new Color(0, 0, 0, 128));
100: handle.setSize(handleSize, handleSize);
101: handle.setVisible(true);
102: handle.addMouseListener(this );
103: handle.addMouseMotionListener(this );
104: add(handle, 0);
105:
106: handle.setCursor(cursor);
107: return handle;
108: }
109:
110: /**
111: * Add this Sizer component to the container so that the specified component
112: * appears to be selected
113: * @param comp the selected component
114: */
115: public void highlightComponent(XGuidePane owner,
116: XPageResource page, Component comp) {
117: ownerScreen = owner;
118: ownerPage = page;
119: target = comp;
120:
121: setupHandles();
122: ownerScreen.add(this , 0);
123:
124: requestFocus();
125: Point pt = comp.getLocation();
126: Rectangle rect = comp.getBounds();
127: Container parent = comp.getParent();
128: setBounds(rect);
129: }
130:
131: /**
132: * Remove the sizer from the parent and hide
133: */
134: public void remove() {
135: setVisible(false);
136: Container parent = target.getParent();
137: Container currentParent = getParent();
138:
139: if (currentParent instanceof JFrame)
140: ((JFrame) currentParent).getContentPane().remove(this );
141: else if (currentParent != null)
142: currentParent.remove(this );
143: }
144:
145: /**
146: * Return the monitored component
147: * @return
148: */
149: public Component getTarget() {
150: return target;
151: }
152:
153: /**
154: * Get the screen with which the highlighted component is associated.
155: * @return the screen that owns the highlighted control
156: */
157: public XPageResource getPageResource() {
158: return ownerPage;
159: }
160:
161: /**
162: * Adjust this component and its children so that the specified rectangle is
163: * highlighted and force any listeneing components to update themselves
164: * @param r the new size
165: */
166: public void adjustBounds(Rectangle r) {
167: setShape(r);
168: r.setLocation(SwingUtilities.convertPoint(ownerScreen, r
169: .getLocation(), target.getParent()));
170: target.setBounds(r);
171: if (sizerListener != null)
172: sizerListener.componentSized();
173: }
174:
175: /**
176: * Updates the targets position to match that of the sizer
177: */
178: public void repositionTarget() {
179: Rectangle r = getBounds();
180: r.setLocation(SwingUtilities.convertPoint(ownerScreen, r
181: .getLocation(), target.getParent()));
182: target.setBounds(r);
183: }
184:
185: /**
186: * Adjust this component and its children so that the specified rectangle is
187: * highlighted
188: * @param r the new size
189: */
190: public void setBounds(Rectangle r) {
191: r.setLocation(SwingUtilities.convertPoint(target.getParent(), r
192: .getLocation(), ownerScreen));
193: setShape(r);
194: }
195:
196: private void setShape(Rectangle r) {
197: super .setBounds(r);
198:
199: lSE.setLocation(r.width - handleSize, r.height - handleSize);
200: lE.setLocation(r.width - handleSize,
201: (r.height - handleSize) / 2);
202: lS.setLocation((r.width - handleSize) / 2, r.height
203: - handleSize);
204: lN.setLocation((r.width - handleSize) / 2, 0);
205: lW.setLocation(0, (r.height - handleSize) / 2);
206: lNE.setLocation(r.width - handleSize, 0);
207: lSW.setLocation(0, r.height - handleSize);
208: if (moveHandle != null)
209: moveHandle.setLocation((r.width - handleSize) / 2,
210: (r.height - handleSize) / 2);
211: }
212:
213: public void mouseExited(MouseEvent e) {
214: }
215:
216: public void mouseEntered(MouseEvent e) {
217: }
218:
219: public void mouseReleased(MouseEvent e) {
220: if (e.isPopupTrigger()) {
221: JPopupMenu popupMenu = new JPopupMenu();
222: getPageHolder().getContextMenu(popupMenu, e);
223:
224: currentProject.getPluginManager().getPluginContextMenu(e,
225: popupMenu);
226: } else {
227: Point pt = e.getPoint();
228: Component comp = (Component) e.getSource();
229: if (target instanceof Container) {
230: PropertyHelper helper = ComponentHelper
231: .getPropertyHelper(target);
232: comp = ((Container) target).findComponentAt(pt);
233: if (comp instanceof GlassPanel)
234: comp = comp.getParent();
235:
236: if ((comp != null)
237: && (helper.allowsChildren() && ((comp
238: .getClass().getName().indexOf(
239: "JViewport") < 0) || getPageHolder()
240: .isAddingComponent()))) {
241: try {
242: MouseEvent me = new MouseEvent(comp, e.getID(),
243: e.getWhen(), e.getModifiers(), pt.x,
244: pt.y, e.getClickCount(), e
245: .isPopupTrigger(), e
246: .getButton());
247: getPageHolder().mouseReleased(me);
248: } catch (Exception ex) {
249: }
250: }
251: }
252:
253: if (e.getSource().equals(this ))
254: this .setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
255: currentHandle = null;
256: if (sizerListener != null)
257: sizerListener.componentSized();
258: }
259: }
260:
261: public void mousePressed(MouseEvent e) {
262: requestFocus();
263: if (e.getSource().equals(this ))
264: this .setCursor(new Cursor(Cursor.MOVE_CURSOR));
265: currentHandle = (Component) e.getSource();
266: startPoint = e.getPoint();
267: }
268:
269: public void mouseClicked(MouseEvent e) {
270: }
271:
272: public void rightButtonClicked(MouseEvent evt) {
273: }
274:
275: public void mouseMoved(MouseEvent e) {
276: }
277:
278: /**
279: * Dynamically resize the component in response to mouse drags.
280: * @param e
281: */
282: public void mouseDragged(MouseEvent e) {
283: if (getPageHolder() == null)
284: return;
285:
286: Vector selectedComponents = getPageHolder()
287: .getSelectedComponents();
288: int numComponents = selectedComponents.size();
289:
290: for (int i = 0; i < numComponents; i++) {
291: XComponentSizer targetSizer = (XComponentSizer) selectedComponents
292: .elementAt(i);
293: Component targetComponent = targetSizer.getTarget();
294:
295: Point mousePoint = e.getPoint();
296: if (e.getSource().equals(this )) {
297: Rectangle r = new Rectangle();
298: Point location = targetSizer.getLocation();
299: Point targetLocation = targetComponent.getLocation();
300:
301: int vert = (startPoint.y - mousePoint.y);
302: int horz = (startPoint.x - mousePoint.x);
303: r.setSize(targetSizer.getSize());
304: r.setLocation((location.x - horz), (location.y - vert));
305: targetSizer.setShape(r);
306: r.setLocation((targetLocation.x - horz),
307: (targetLocation.y - vert));
308: targetComponent.setBounds(r);
309: } else if (currentHandle != null) {
310: Rectangle r = new Rectangle();
311:
312: int vert = 0;
313: int horz = 0;
314: Point location = targetSizer.getLocation();
315: Dimension size = targetSizer.getSize();
316: vert = mousePoint.y - startPoint.y;
317: horz = mousePoint.x - startPoint.x;
318:
319: if (e.getSource().equals(lSE)) {
320: r.setLocation(location);
321: r
322: .setSize((size.width + horz),
323: (size.height + vert));
324: } else if (e.getSource().equals(lS)) {
325: horz = 0;
326: r.setLocation(location);
327: r
328: .setSize((size.width + horz),
329: (size.height + vert));
330: } else if (e.getSource().equals(lE)) {
331: vert = 0;
332: r.setLocation(location);
333: r
334: .setSize((size.width + horz),
335: (size.height + vert));
336: } else if (e.getSource().equals(lN)) {
337: horz = 0;
338: r.setLocation(location.x, (location.y + vert));
339: r.setSize(size.width, (size.height - vert));
340: } else if (e.getSource().equals(lW)) {
341: vert = 0;
342: r.setLocation(location.x + horz, location.y);
343: r.setSize(size.width - horz, size.height);
344: } else if (e.getSource().equals(lNE)) {
345: r.setLocation(location.x, location.y + vert);
346: r
347: .setSize((size.width + horz),
348: (size.height - vert));
349: } else if (e.getSource().equals(lSW)) {
350: r.setLocation(location.x + horz, location.y);
351: r.setSize(size.width - horz, (size.height + vert));
352: } else if (e.getSource().equals(lNW)) {
353: r.setLocation(location.x + horz,
354: (location.y + vert));
355: r.setSize(size.width - horz, (size.height - vert));
356: } else if (e.getSource().equals(moveHandle)) {
357: r.setSize(getSize());
358: r.setLocation((location.x - horz),
359: (location.y - vert));
360: }
361:
362: int minSize = 5;
363: if (r.getHeight() < minSize)
364: r.setSize((int) r.getWidth(), minSize);
365: if (r.getWidth() < minSize)
366: r.setSize(minSize, (int) r.getHeight());
367:
368: targetSizer.setShape(r);
369: r.setLocation(SwingUtilities.convertPoint(ownerScreen,
370: r.getLocation(), target.getParent()));
371: targetComponent.setBounds(r);
372: }
373: }
374: }
375:
376: /**
377: * Get the page that owns this componet
378: * @return
379: */
380: public XPage getPage() {
381: Component c = target;
382: while ((c != null) && !(c instanceof XPage))
383: c = c.getParent();
384:
385: if (c instanceof XPage)
386: return (XPage) c;
387:
388: return null;
389: }
390:
391: protected XPageHolder getPageHolder() {
392: Component c = getPage();
393: while ((c != null) && !(c instanceof XPageHolder))
394: c = c.getParent();
395:
396: if (c instanceof XPageHolder)
397: return (XPageHolder) c;
398:
399: return null;
400: }
401:
402: public void focusGained(FocusEvent e) {
403: }
404:
405: public void focusLost(FocusEvent e) {
406: repaint();
407: }
408:
409: public boolean isFocusable() {
410: return true;
411: }
412:
413: public boolean isEnabled() {
414: return true;
415: }
416: }
|