001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.xml.schema.abe;
043:
044: import java.awt.BasicStroke;
045: import java.awt.Color;
046: import java.awt.Component;
047: import java.awt.Dimension;
048: import java.awt.GradientPaint;
049: import java.awt.Graphics;
050: import java.awt.Graphics2D;
051: import java.awt.Point;
052: import java.awt.Polygon;
053: import java.awt.Rectangle;
054: import java.awt.Shape;
055: import java.awt.Stroke;
056: import java.awt.dnd.DropTargetDragEvent;
057: import java.awt.dnd.DropTargetDropEvent;
058: import java.awt.dnd.DropTargetEvent;
059: import java.awt.event.ComponentEvent;
060: import java.awt.event.ComponentListener;
061: import java.awt.event.ContainerEvent;
062: import java.awt.event.ContainerListener;
063: import java.awt.event.MouseAdapter;
064: import java.awt.event.MouseEvent;
065: import java.util.ArrayList;
066: import javax.swing.JLabel;
067: import javax.swing.SwingUtilities;
068: import org.netbeans.modules.xml.axi.AXIComponent;
069: import org.netbeans.modules.xml.axi.AXIContainer;
070: import org.netbeans.modules.xml.axi.ContentModel;
071: import org.netbeans.modules.xml.axi.Element;
072: import org.netbeans.modules.xml.schema.abe.nodes.ABEAbstractNode;
073:
074: /**
075: *
076: *
077: * @author Todd Fast, todd.fast@sun.com
078: */
079: public abstract class TagPanel extends ABEBaseDropPanel implements
080: ComponentListener {
081:
082: private static final int X_OFFSET = 0;
083: private static final int Y_OFFSET = 0;
084: private static final int X_SHADOW_OFFSET = 4;
085: private static final int Y_SHADOW_OFFSET = 4;
086: public static final int BOTTOM_PAD = Y_SHADOW_OFFSET + 1;
087:
088: private ElementPanel elementPanel;
089: private boolean hover;
090: private String tagName;
091: private boolean readonlyTag;
092:
093: private static final int TAG_HEIGHT = 29;
094:
095: private int XFUDGE = 3;
096:
097: protected ArrayList<Component> excludePaintComponentList = new ArrayList<Component>();
098:
099: /**
100: *
101: *
102: */
103: public TagPanel(ElementPanel elementPanel, InstanceUIContext context) {
104: super (context);
105: this .elementPanel = elementPanel;
106: initialize();
107: }
108:
109: /**
110: *
111: *
112: */
113: private void initialize() {
114: setOpaque(false);
115: setBackground(Color.WHITE);
116:
117: int height = InstanceDesignConstants.TAG_FONT.getSize() * 2
118: + BOTTOM_PAD;
119: setPreferredSize(new Dimension(100, height));
120: // setMinimumSize(new Dimension(100,height));
121: initMouseListener();
122: addContainerListener(new ContainerListener() {
123: public void componentAdded(ContainerEvent e) {
124: e.getComponent().addComponentListener(TagPanel.this );
125: forceSizeRecalculate();
126: }
127:
128: public void componentRemoved(ContainerEvent e) {
129: e.getComponent().removeComponentListener(TagPanel.this );
130: forceSizeRecalculate();
131: }
132: });
133: }
134:
135: public void removeElement() {
136: if (getElementPanel().getParent() != null)
137: getElementPanel().removeElement();
138: }
139:
140: protected void initMouseListener() {
141: addMouseListener(new MouseAdapter() {
142: public void mouseReleased(MouseEvent e) {
143: mouseClickedActionHandler(e, true);
144: }
145:
146: public void mouseClicked(MouseEvent e) {
147: mouseClickedActionHandler(e, false);
148: }
149:
150: public void mousePressed(MouseEvent e) {
151: mouseClickedActionHandler(e, true);
152: }
153: });
154: }
155:
156: protected void mouseClickedActionHandler(MouseEvent e,
157: boolean handelPopupOnly) {
158: if (e.getClickCount() == 1) {
159: if (e.isPopupTrigger()) {
160: context.getMultiComponentActionManager().showPopupMenu(
161: e, this );
162: return;
163: }
164: if (handelPopupOnly)
165: return;
166: //the tag is selected
167: if (e.isControlDown())
168: context.getComponentSelectionManager()
169: .addToSelectedComponents(this );
170: else
171: context.getComponentSelectionManager()
172: .setSelectedComponent(this );
173: }
174: }
175:
176: ////////////////////////////////////////////////////////////////////////////
177: // Accessors and mutators
178: ////////////////////////////////////////////////////////////////////////////
179:
180: /**
181: *
182: *
183: */
184: public ElementPanel getElementPanel() {
185: return elementPanel;
186: }
187:
188: /**
189: *
190: *
191: */
192: /*pkg*/boolean isHover() {
193: return hover;
194: }
195:
196: /**
197: *
198: *
199: */
200: /*pkg*/void setHover(boolean value) {
201: boolean oldHover = hover;
202: if (oldHover != value) {
203: hover = value;
204: repaint();
205: }
206: }
207:
208: /**
209: *
210: *
211: */
212: public String getTagName() {
213: return tagName;
214: }
215:
216: /**
217: *
218: *
219: */
220: public void setTagName(String value) {
221: tagName = value;
222: }
223:
224: Color fillTopColor = InstanceDesignConstants.TAG_BG_NORMAL_TOP_GRADIENT_COLOR;
225: Color fillBottomColor = InstanceDesignConstants.TAG_BG_NORMAL_BOTTOM_GRADIENT_COLOR;
226:
227: ////////////////////////////////////////////////////////////////////////////
228: // Paint methods
229: ////////////////////////////////////////////////////////////////////////////
230:
231: /**
232: *
233: *
234: */
235: public void paintComponent(Graphics g) {
236: Graphics2D g2d = (Graphics2D) g;
237:
238: super .paintComponent(g2d);
239:
240: fillTopColor = InstanceDesignConstants.TAG_BG_NORMAL_TOP_GRADIENT_COLOR;
241: fillBottomColor = InstanceDesignConstants.TAG_BG_NORMAL_BOTTOM_GRADIENT_COLOR;
242:
243: setDrawParamsForSharedElement(g2d);
244: boolean selected = false;
245: //set proper colors
246: if (isHover()) {
247: fillTopColor = InstanceDesignConstants.DARK_BLUE;//Color.WHITE;
248: fillBottomColor = InstanceDesignConstants.DARK_BLUE;//InstanceDesignConstants.XP_ORANGE;
249: } else if (context.getComponentSelectionManager().isSelected(
250: this )) {
251: selected = true;
252: }
253:
254: Shape tag = getTagShape();
255: Rectangle tagBounds = tag.getBounds();
256:
257: // Draw shadow
258: g.translate(X_SHADOW_OFFSET, Y_SHADOW_OFFSET);
259: g2d.setColor(new Color(240, 240, 240));
260: g2d.fill(tag);
261:
262: g.translate(-1, -1);
263: g2d.setColor(new Color(224, 224, 224));
264: g2d.fill(tag);
265:
266: g.translate(-1, -1);
267: g2d.setColor(new Color(192, 192, 192));
268: g2d.fill(tag);
269:
270: // Draw main tag body
271:
272: g.translate(2, 2);
273: g.translate(-X_SHADOW_OFFSET, -Y_SHADOW_OFFSET);
274: // fill tag
275: float x1, y1, x2, y2;
276: x1 = x2 = (float) tagBounds.getX();
277: y2 = (float) tagBounds.getY();
278: for (int i = 1; i <= getRowCount(); i++) {
279: y1 = y2;
280: y2 = y2 + getTagHeight() - BOTTOM_PAD;
281: GradientPaint fill = new GradientPaint(x1, y1,
282: fillTopColor, x2, y2, fillBottomColor, false);
283: g2d.setPaint(fill);
284: g2d.fill(tag);
285: }
286:
287: //draw row separation lines
288: int lineY = (int) tagBounds.getY();
289: g2d.setColor(fillBottomColor);
290: Stroke stroke = new BasicStroke(2f);
291: Stroke oldstroke = null;
292: oldstroke = g2d.getStroke();
293: g2d.setStroke(stroke);
294: for (int i = 1; i < getRowCount(); i++) {
295: lineY = lineY + getTagHeight() - BOTTOM_PAD;
296: g2d.drawLine(extremeLeftX + 1, lineY, extremeRightX - 1,
297: lineY);
298: }
299: g2d.setStroke(oldstroke);
300:
301: // draw Outline
302: g2d.setColor(InstanceDesignConstants.TAG_OUTLINE_COLOR);
303: oldstroke = null;
304: if (selected) {
305: oldstroke = g2d.getStroke();
306: stroke = new BasicStroke(2f);
307: g2d.setStroke(stroke);
308: g2d.setColor(InstanceDesignConstants.XP_ORANGE);
309: }
310:
311: g2d.draw(tag);
312:
313: if (selected && (oldstroke != null)) {
314: g2d.setStroke(oldstroke);
315: }
316:
317: resetDrawParamsForSharedElement(g2d);
318: }
319:
320: /**
321: *
322: *
323: */
324: protected int getA() {
325: // Height could be zero before the component is laid out, so use
326: // the preferred height (which should be the final height)
327: /*int h = getHeight();
328: if (h == 0)
329: h = getPreferredSize().height;*/
330: int h = TAG_HEIGHT;
331: return (h - BOTTOM_PAD) / 2;
332: }
333:
334: /**
335: *
336: *
337: */
338: /* protected Shape getTagShape() {
339: Graphics g=getGraphics();
340: return getTagShape();
341: }*/
342:
343: int tagNosePointOffset;
344:
345: public int getTagNosePointOffset() {
346: int h = TAG_HEIGHT - BOTTOM_PAD;
347: tagNosePointOffset = h / 2;
348: return tagNosePointOffset;
349: }
350:
351: /**
352: *
353: *
354: */
355: private Shape _getTagShape(Graphics g) {
356: int h = TAG_HEIGHT - BOTTOM_PAD;
357: int xo = X_OFFSET;
358: int yo = Y_OFFSET;
359: int ym = h / 2;
360: int a = getA(); // ym-yo;
361: int w = getAbsoluteWidth();//(int) getPreferredSize().getWidth() + getA()) - 2*xo;
362:
363: tagNosePointOffset = ym;
364:
365: /*
366: Starting from the left vertical middle point and moving clockwise:
367:
368: /-----------------\
369: / \
370: \ /
371: \-----------------/
372:
373: xo, ym
374: xo+a, yo
375: w-xo-a, yo
376: w-xo, ym
377: w-xo-a, h-yo
378: xo+a, h-yo
379: */
380:
381: return new Polygon(new int[] { xo, xo + a, w - xo - a, w - xo,
382: w - xo - a, xo + a }, new int[] { ym, yo, yo, ym,
383: h - yo, h - yo }, 6);
384: }
385:
386: private int extremeLeftX;
387: private int extremeRightX;
388: private Point leftBottomPoint;
389: private Point rightBottomPoint;
390: private Point rightNosePoint;
391: private Point leftNosePoint;
392:
393: public Shape getTagShape() {
394: Rectangle rect = getChildrenAreaUnion();
395: //Rectangle realRect = g.getClipBounds();
396: int h = TAG_HEIGHT - BOTTOM_PAD;
397: int a = getA(); // ym-yo;
398: int x = rect.x;//rect.x;
399: int y = rect.y - 2;
400: int H = this .getHeight() - BOTTOM_PAD;
401: int W = rect.width;
402: tagNosePointOffset = h / 2;
403: /*
404: Starting from the left vertical middle point and moving clockwise:
405:
406: (x,y) /--------------------| (x+W, y)
407: (x-a,y+h/2) / |
408: \ |
409: (x, y+h),(x, y+h) \ |
410: | \----| (x+w1, y+H-h), (x+W, y+H-h)
411: | \
412: | / (x+w1+a, y+H-(h/2))
413: (x, y+H)|---------------/((x+w1, y+H);
414:
415:
416: */
417:
418: if (getRowCount() > 1)
419: W += 8;
420:
421: int w1 = W;
422: if (getEndSlash() != null) {
423: w1 = getEndSlash().getBounds().x;
424: }
425: extremeLeftX = x;
426: extremeRightX = x + W;
427: leftBottomPoint = new Point(x, y + h);
428: rightBottomPoint = new Point(x + w1, y + H);
429: rightNosePoint = new Point(x + w1 + a, y + H - (h / 2));
430: leftNosePoint = new Point(x - a, y + h / 2);
431: return new Polygon(new int[] { x - a, x, x + W, x + W, x + w1,
432: x + w1 + a, x + w1, x, x, x }, new int[] { y + h / 2,
433: y, y, y + H - h, y + H - h, y + H - (h / 2), y + H,
434: y + H, y + h, y + h }, 10);
435: }
436:
437: private int getAbsoluteWidth() {
438: int width = 0;
439: int finalX = 0;
440: for (Component child : getComponents()) {
441: int x;
442: x = child.getBounds().x;
443: x += child.getPreferredSize().width;
444: if (x > finalX)
445: finalX = x;
446: }
447: finalX += getA();
448: return finalX;
449: }
450:
451: private Rectangle getChildrenAreaUnion() {
452: Component children[] = getComponents();
453: if (children.length <= 0)
454: return null;
455: Rectangle current;
456: current = children[1].getBounds();
457: for (Component child : children) {
458: if (excludePaintComponentList.contains(child))// || !child.isVisible())
459: continue;
460: current = SwingUtilities.computeUnion(current.x, current.y,
461: current.width, current.height, child.getBounds());
462: }
463: return current;
464: }
465:
466: //sub-class to override
467: public int getInterComponentSpacing() {
468: return 0;
469: }
470:
471: //Following set of methods needed for the tag size calculation and horizontal bar display logic
472: public Dimension _getPreferredSize() {
473: int width = 0;
474: int maxWidth = 0;
475: int propsWidth = 0;
476: for (Component child : this .getComponents()) {
477: if (!child.isVisible())
478: continue;
479: Dimension dim = child.getPreferredSize();
480: width += dim.width + getInterComponentSpacing();
481: maxWidth = maxWidth > dim.width ? maxWidth : dim.width;
482: if (child instanceof ElementPropertiesPanel)
483: propsWidth = dim.width;
484: }
485: if (getRowCount() > 1) {
486: width = maxWidth * StartTagPanel.NO_OF_ATTRS_PER_ROW
487: + getInterComponentSpacing()
488: * StartTagPanel.NO_OF_ATTRS_PER_ROW * 2 + getA()
489: * 2 + propsWidth + 25;
490: } else {
491: width += maxWidth + getA() * 2 + 20;
492: width += (getElementPanel().getAXIContainer().getName()
493: .length() < 3) ? 10 : 0;
494: }
495: return new Dimension(width,
496: ((TAG_HEIGHT - BOTTOM_PAD) * getRowCount())
497: + BOTTOM_PAD);
498: }
499:
500: boolean recalculateRequired = true;
501: Dimension myDim;
502:
503: public Dimension getPreferredSize() {
504: synchronized (this ) {
505: if (recalculateRequired) {
506: myDim = _getPreferredSize();
507: recalculateRequired = false;
508: }
509: return myDim;
510: }
511: }
512:
513: public Dimension getMinimumSize() {
514: return getPreferredSize();
515: }
516:
517: public Dimension getMaximumSize() {
518: return getPreferredSize();
519: }
520:
521: public static int getTagHeight() {
522: return TAG_HEIGHT;
523: }
524:
525: //DND events
526: public void drop(DropTargetDropEvent event) {
527: setHover(false);
528: }
529:
530: public void dragExit(DropTargetEvent event) {
531: setHover(false);
532: }
533:
534: public void dragOver(DropTargetDragEvent event) {
535: setHover(true);
536: }
537:
538: public void dragEnter(DropTargetDragEvent event) {
539: setHover(true);
540: }
541:
542: public ABEAbstractNode getNBNode() {
543: return getElementPanel().getNBNode();
544: }
545:
546: public AXIComponent getAXIComponent() {
547: return getElementPanel().getAXIContainer();
548: }
549:
550: public int getRowCount() {
551: return 1;
552: }
553:
554: public boolean isReadonlyTag() {
555: return readonlyTag;
556: }
557:
558: public void setReadonlyTag(boolean readonlyTag) {
559: this .readonlyTag = readonlyTag;
560: }
561:
562: private void setDrawParamsForSharedElement(Graphics2D g2d) {
563: AXIContainer acon = getElementPanel().getAXIContainer();
564: //ContentModel cm = acon.getContentModel();
565: boolean reference = false;
566: if (acon instanceof Element)
567: reference = ((Element) acon).isReference();
568: if (acon.isShared() || reference) {
569: fillTopColor = InstanceDesignConstants.TAG_BG_SHARED_TOP_GRADIENT_COLOR;
570: fillBottomColor = InstanceDesignConstants.TAG_BG_SHARED_BOTTOM_GRADIENT_COLOR;
571: }
572: if (acon.isReadOnly()) {
573: fillTopColor = InstanceDesignConstants.TAG_BG_READONLY_TOP_GRADIENT_COLOR;
574: fillBottomColor = InstanceDesignConstants.TAG_BG_READONLY_BOTTOM_GRADIENT_COLOR;
575: }
576:
577: }
578:
579: private void resetDrawParamsForSharedElement(Graphics2D g2d) {
580: }
581:
582: public Point getLeftBottomPoint() {
583: return leftBottomPoint;
584: }
585:
586: public Point getRightBottomPoint() {
587: return rightBottomPoint;
588: }
589:
590: public Point getRightNosePoint() {
591: return rightNosePoint;
592: }
593:
594: public Point getLeftNosePoint() {
595: return leftNosePoint;
596: }
597:
598: public JLabel getEndSlash() {
599: return null;
600: }
601:
602: public void componentShown(ComponentEvent e) {
603: forceSizeRecalculate();
604: }
605:
606: public void componentResized(ComponentEvent e) {
607: forceSizeRecalculate();
608: }
609:
610: public void componentMoved(ComponentEvent e) {
611: forceSizeRecalculate();
612: }
613:
614: public void componentHidden(ComponentEvent e) {
615: forceSizeRecalculate();
616: }
617:
618: public void forceSizeRecalculate() {
619: recalculateRequired = true;
620: }
621: }
|