0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.xml.schema.abe;
0043:
0044: import java.awt.Color;
0045: import java.awt.Component;
0046: import java.awt.Cursor;
0047: import java.awt.Dimension;
0048: import java.awt.Font;
0049: import java.awt.Graphics;
0050: import java.awt.Graphics2D;
0051: import java.awt.Point;
0052: import java.awt.Polygon;
0053: import java.awt.Rectangle;
0054: import java.awt.dnd.DropTargetDragEvent;
0055: import java.awt.dnd.DropTargetDropEvent;
0056: import java.awt.dnd.DropTargetEvent;
0057: import java.awt.event.ActionEvent;
0058: import java.awt.event.ActionListener;
0059: import java.awt.event.KeyEvent;
0060: import java.awt.event.KeyListener;
0061: import java.awt.event.MouseAdapter;
0062: import java.awt.event.MouseEvent;
0063: import java.beans.PropertyChangeEvent;
0064: import java.beans.PropertyChangeListener;
0065: import java.io.IOException;
0066: import java.util.ArrayList;
0067: import java.util.Collections;
0068: import java.util.List;
0069: import javax.swing.Box;
0070: import javax.swing.JLabel;
0071: import javax.swing.JPanel;
0072: import javax.swing.JTextField;
0073: import javax.swing.SpringLayout;
0074: import javax.swing.SwingUtilities;
0075: import org.netbeans.modules.xml.axi.AXIComponent;
0076: import org.netbeans.modules.xml.axi.AXIContainer;
0077: import org.netbeans.modules.xml.axi.AXIModel;
0078: import org.netbeans.modules.xml.axi.AXIType;
0079: import org.netbeans.modules.xml.axi.AbstractAttribute;
0080: import org.netbeans.modules.xml.axi.AbstractElement;
0081: import org.netbeans.modules.xml.axi.AnyElement;
0082: import org.netbeans.modules.xml.axi.Attribute;
0083: import org.netbeans.modules.xml.axi.Compositor;
0084: import org.netbeans.modules.xml.axi.Element;
0085: import org.netbeans.modules.xml.axi.datatype.Datatype;
0086: import org.netbeans.modules.xml.schema.abe.action.AttributeOnElementNewType;
0087: import org.netbeans.modules.xml.schema.abe.action.ElementOnElementNewType;
0088: import org.netbeans.modules.xml.schema.abe.palette.DnDHelper;
0089: import org.openide.util.NbBundle;
0090: import org.openide.util.datatransfer.NewType;
0091:
0092: /**
0093: *
0094: *
0095: */
0096: public class StartTagPanel extends TagPanel {
0097: protected static final long serialVersionUID = 7526472295622776147L;
0098:
0099: private ExpandCollapseButton expandButton;
0100:
0101: public StartTagPanel(final ElementPanel elementPanel,
0102: InstanceUIContext context) {
0103: super (elementPanel, context);
0104: //add listener for name changes
0105: elementPanel.getAXIContainer().addPropertyChangeListener(
0106: new ModelEventMediator(this , elementPanel
0107: .getAXIContainer()) {
0108: public void _propertyChange(PropertyChangeEvent evt) {
0109: String property = evt.getPropertyName();
0110: if (property.equals(Element.PROP_NAME)) {
0111: setTagName(getElementPanel()
0112: .getAXIContainer().getName());
0113: forceSizeRecalculate();
0114: revalidate();
0115: repaint();
0116: } else if (property
0117: .equals(Attribute.PROP_ATTRIBUTE)
0118: || property
0119: .equals(Attribute.PROP_ATTRIBUTE_REF)) {
0120: updateAttributes();
0121: if (evt.getNewValue() != null) {
0122: //its a new attribute add event
0123: if ((StartTagPanel.super .context
0124: .getUserActedComponent() == StartTagPanel.this )) {
0125: showAttributes();
0126: showAttributeEditFor((Attribute) evt
0127: .getNewValue());
0128: StartTagPanel.super .context
0129: .resetUserActedComponent();
0130: }
0131: }
0132: } else if (evt.getPropertyName().equals(
0133: Element.PROP_TYPE)) {
0134: //indirectly update the element properties panel
0135: updateAttributes();
0136: }
0137: }
0138: });
0139:
0140: initialize();
0141: initKeyListener();
0142: }
0143:
0144: protected void initKeyListener() {
0145: addKeyListener(new KeyListener() {
0146: public void keyPressed(KeyEvent e) {
0147: if (e.getKeyCode() == e.VK_F2) {
0148: tagNameLabel.showEditor();
0149: }
0150: if (context.getFocusTraversalManager()
0151: .isFocusChangeEvent(e))
0152: context.getFocusTraversalManager().handleEvent(e,
0153: StartTagPanel.this );
0154: }
0155:
0156: public void keyReleased(KeyEvent e) {
0157: }
0158:
0159: public void keyTyped(KeyEvent e) {
0160: if (e.getKeyChar() == e.VK_SPACE) {
0161: tagNameLabel.showEditor();
0162: } else if (e.getKeyChar() == e.VK_E) {
0163: //create a new child element
0164: for (NewType nt : getNBNode().getNewTypes()) {
0165: if (nt instanceof ElementOnElementNewType) {
0166: try {
0167: nt.create();
0168: } catch (IOException ex) {
0169: }
0170: return;
0171: }
0172: }
0173: } else if (e.getKeyChar() == e.VK_A) {
0174: for (NewType nt : getNBNode().getNewTypes()) {
0175: //create a new attribute
0176: if (nt instanceof AttributeOnElementNewType) {
0177: try {
0178: nt.create();
0179: } catch (IOException ex) {
0180: }
0181: return;
0182: }
0183: }
0184: }
0185: }
0186: });
0187: }
0188:
0189: boolean initialized = false;
0190: SpringLayout startTagPanelLayout;
0191: Color tagNameLabelColor = InstanceDesignConstants.TAG_NAME_COLOR;
0192:
0193: private void initialize() {
0194: initialized = true;
0195: setOpaque(false);
0196: startTagPanelLayout = new SpringLayout();
0197: setLayout(startTagPanelLayout);
0198:
0199: attributeCollapseButton
0200: .setToolTipText(NbBundle.getMessage(
0201: StartTagPanel.class,
0202: "TTP_ATTR_EXPAND_COLLAPSE_BUTTON"));
0203: attributeCountLabel
0204: .setForeground(InstanceDesignConstants.ITEM_COUNT_COLOR);
0205:
0206: expandButton = getElementPanel().getExpandButton();
0207: add(expandButton);
0208: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0209: expandButton, getA(), SpringLayout.WEST, this );
0210: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0211: expandButton, LABEL_HEAD_ROOM_SPACE + 5,
0212: SpringLayout.NORTH, this );
0213: //excludePaintComponentList.add(expandButton);
0214:
0215: tagNameLabel = new InplaceEditableLabel();
0216: tagNameLabel.setToolTipText(NbBundle.getMessage(
0217: StartTagPanel.class, "TTP_ELEMENT_NAME_LABEL"));
0218:
0219: tagNameLabelColor = InstanceDesignConstants.TAG_NAME_COLOR;
0220:
0221: if (getElementPanel().getAXIContainer().isReadOnly()
0222: || (getElementPanel().getAXIContainer() instanceof AnyElement)) {
0223: tagNameLabelColor = InstanceDesignConstants.TAG_NAME_READONLY_COLOR;
0224: tagNameLabel.setToolTipText(NbBundle.getMessage(
0225: StartTagPanel.class,
0226: "TTP_ELEMENT_NAME_LABEL_READONLY"));
0227: } else {
0228: if (getElementPanel().getAXIContainer().isShared()) {
0229: tagNameLabelColor = InstanceDesignConstants.TAG_NAME_SHARED_COLOR;
0230: tagNameLabel.setToolTipText(NbBundle.getMessage(
0231: StartTagPanel.class,
0232: "TTP_ELEMENT_NAME_LABEL_SHARED"));
0233: }
0234: }
0235:
0236: /*if(getElementPanel().getAXIContainer().isReadOnly()){
0237: tagNameLabel.setIcon(UIUtilities.getImageIcon("import-include-redefine.png"));
0238: }*/
0239: tagNameLabel.setForeground(tagNameLabelColor);
0240:
0241: getEndSlash().setForeground(tagNameLabel.getForeground());
0242: initTagEditListener();
0243:
0244: Component hgap = Box.createHorizontalStrut(5);
0245: add(hgap);
0246: startTagPanelLayout
0247: .putConstraint(SpringLayout.WEST, hgap, getA()
0248: + INTER_PANEL_SPACE + 8, SpringLayout.WEST,
0249: this );
0250: startTagPanelLayout.putConstraint(SpringLayout.NORTH, hgap,
0251: LABEL_HEAD_ROOM_SPACE, SpringLayout.NORTH, this );
0252:
0253: //setup the tagLabel
0254: add(tagNameLabel);
0255: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0256: tagNameLabel, 0, SpringLayout.EAST, hgap);
0257: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0258: tagNameLabel, LABEL_HEAD_ROOM_SPACE,
0259: SpringLayout.NORTH, this );
0260:
0261: hgap = Box.createHorizontalStrut(5);
0262: add(hgap);
0263: startTagPanelLayout.putConstraint(SpringLayout.WEST, hgap, 0,
0264: SpringLayout.EAST, tagNameLabel);
0265: startTagPanelLayout.putConstraint(SpringLayout.NORTH, hgap,
0266: LABEL_HEAD_ROOM_SPACE, SpringLayout.NORTH, this );
0267:
0268: firstRowLastComp = hgap;
0269: //addElementPropertiesPanel();
0270:
0271: updateTagName();
0272: addNonAttributeComponents();
0273: updateAttributes();
0274: addSelectionListener();
0275: }
0276:
0277: Component lastNonAtribComponent;
0278: Component lastAtribComponent;
0279:
0280: protected void initTagEditListener() {
0281:
0282: tagNameLabel
0283: .addCtrlClickHandler(new InplaceEditableLabel.CtrlClickHandler() {
0284: public void handleCtrlClick() {
0285: getNBNode().showSuperDefinition();
0286: }
0287: });
0288:
0289: tagNameLabel
0290: .setInputValidator(new InputValidator() {
0291: public boolean isStringValid(String input) {
0292: return org.netbeans.modules.xml.xam.dom.Utils
0293: .isValidNCName(input);
0294: }
0295: }, NbBundle.getMessage(StartTagPanel.class,
0296: "MSG_NOT_A_NCNAME"));
0297: tagNameLabel
0298: .addPropertyChangeListener(new PropertyChangeListener() {
0299: public void propertyChange(PropertyChangeEvent evt) {
0300: if (evt.getPropertyName().equals(
0301: tagNameLabel.PROPERTY_MODE_CHANGE)) {
0302: if (evt.getNewValue() == InplaceEditableLabel.Mode.EDIT) {
0303: //user selected edit give the editor JComponent
0304: //show a text field
0305: final JTextField field = new JTextField(
0306: getElementPanel()
0307: .getAXIContainer()
0308: .getName());
0309: field.select(0, field.getText()
0310: .length());
0311: field
0312: .addActionListener(new ActionListener() {
0313: public void actionPerformed(
0314: ActionEvent e) {
0315: String newName = field
0316: .getText();
0317: if (getElementPanel()
0318: .getAXIContainer()
0319: .getName()
0320: .equals(newName))
0321: return;
0322: //do validation
0323: if (org.netbeans.modules.xml.xam.dom.Utils
0324: .isValidNCName(newName)) {
0325: field
0326: .setCursor(new Cursor(
0327: Cursor.WAIT_CURSOR));
0328: try {
0329: if (firstTimeRename)
0330: getNBNode()
0331: .setNameInModel(
0332: newName);
0333: else
0334: setTagNameInModel(newName);
0335: firstTimeRename = false;
0336: } finally {
0337: field
0338: .setCursor(new Cursor(
0339: Cursor.DEFAULT_CURSOR));
0340: }
0341: }
0342: }
0343: });
0344: if (getElementPanel().getAXIContainer()
0345: .isShared()) {
0346: String str = NbBundle.getMessage(
0347: StartTagPanel.class,
0348: "MSG_SHARED_ELEMENT_EDIT");
0349: tagNameLabel.setEditInfoText(str,
0350: context);
0351: }
0352: if (!getElementPanel()
0353: .getAXIContainer().isReadOnly()) {
0354: if (getElementPanel()
0355: .getAXIContainer() instanceof AnyElement) {
0356: String str = NbBundle
0357: .getMessage(
0358: StartTagPanel.class,
0359: "MSG_ANY_ELEMENT_EDIT");
0360: tagNameLabel.setEditInfoText(
0361: str, context);
0362: } else {
0363: tagNameLabel
0364: .setInlineEditorComponent(field);
0365: }
0366: } else {
0367: String str = NbBundle
0368: .getMessage(
0369: StartTagPanel.class,
0370: "MSG_READONLY_ELEMENT_EDIT");
0371: tagNameLabel.setEditInfoText(str,
0372: context);
0373: }
0374: }
0375: }
0376: }
0377: });
0378: }
0379:
0380: private void setTagNameInModel(String name) {
0381: getNBNode().setName(name);
0382: }
0383:
0384: /**
0385: *
0386: *
0387: */
0388: public void setTagName(String value) {
0389: String tagName = value;
0390: tagNameLabel.setText(tagName);
0391: }
0392:
0393: /**
0394: *
0395: *
0396: */
0397: public void updateTagName() {
0398: setTagName(getElementPanel().getAXIContainer().getName());
0399: }
0400:
0401: private void showAttributeEditFor(Attribute attr) {
0402: if (componentList != null) {
0403: for (Component child : componentList) {
0404: if (child instanceof AttributePanel) {
0405: final AttributePanel attrP = (AttributePanel) child;
0406: if (attrP.getAttribute() == attr) {
0407: context.getComponentSelectionManager()
0408: .setSelectedComponent(attrP);
0409: SwingUtilities.invokeLater(new Runnable() {
0410: public void run() {
0411: UIUtilities
0412: .scrollViewTo(attrP, context);
0413: attrP.showEditorForName(true);
0414: }
0415: });
0416: return;
0417: }
0418: }
0419: }
0420: }
0421: }
0422:
0423: /**
0424: *
0425: *
0426: */
0427: Component firstRowLastComp;
0428:
0429: public void updateAttributes() {
0430: updateAttributeCountLabel();
0431: //Remove the existing panels
0432: if (componentList != null) {
0433: for (Component panel : componentList) {
0434: //except firstTweener remove everything
0435: if (panel != firstTweener) {
0436: startTagPanelLayout.removeLayoutComponent(panel);
0437: remove(panel);
0438: }
0439: }
0440: }
0441:
0442: componentList = new ArrayList<Component>();
0443: //firstTweener has to be added for the drop logic to work
0444: componentList.add(firstTweener);
0445:
0446: int attrCount = getElementPanel().getAXIContainer()
0447: .getAttributes().size();
0448: if (attrCount > 0) {
0449: if (!attributeCollapseButton.isVisible()) {
0450: attributeCollapseButton.setVisible(true);
0451: attributeCountLabel.setVisible(true);
0452: //then may be user dropped an attr. So Default expand.
0453: if (context.isUserInducedEventMode())
0454: attributeCollapseButton.setText("-");
0455: }
0456: } else {
0457: if (attributeCollapseButton.isVisible()) {
0458: attributeCollapseButton.setVisible(false);
0459: attributeCountLabel.setVisible(false);
0460: }
0461: }
0462:
0463: lastAtribComponent = firstTweener;
0464: firstRowLastComp = null;
0465: if (attributesAreShown) {
0466: addAttributes();
0467: if (firstRowLastComp == null) {
0468: //there may be no attrs
0469: firstRowLastComp = getEndSlash();
0470: }
0471: } else {
0472: //makesure that the collapse button moves closer to tagNameLabel
0473: hgap.setPreferredSize(new Dimension(0, 0));
0474: firstRowLastComp = getEndSlash();
0475: }
0476:
0477: addEndSlashLabel();
0478: addElementPropertiesPanel();
0479: revalidate();
0480: //repaint();
0481: getElementPanel().repaint();
0482: }
0483:
0484: static final String locHidden = NbBundle.getMessage(
0485: StartTagPanel.class, "LBL_HIDDEN");
0486: static final String locAttr = NbBundle.getMessage(
0487: StartTagPanel.class, "LBL_ATTRIBUTE");
0488: static final String locAttrs = NbBundle.getMessage(
0489: StartTagPanel.class, "LBL_ATTRIBUTES");
0490:
0491: protected void addAttributeCountLabel() {
0492: if (attributesAreShown)
0493: //dont show anything if the attributes are seen
0494: return;
0495: int count = getElementPanel().getAXIContainer().getAttributes()
0496: .size();
0497: if (count > 0) {
0498: String hidden = (attributesAreShown) ? "" : " " + locHidden;
0499: String attributeStr = "";
0500: if (!attributesAreShown)
0501: attributeStr = (count == 1) ? " " + locAttr : " "
0502: + locAttrs;
0503:
0504: String str = "[" + count + attributeStr + hidden + "]";
0505: String countStr = "[" + count + "]";
0506: attributeCountLabel.setText(countStr);
0507: attributeCountLabel.setToolTipText(str);
0508: add(attributeCountLabel);
0509: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0510: attributeCountLabel, 0/*INTER_PANEL_SPACE*/,
0511: SpringLayout.EAST, lastAtribComponent);
0512: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0513: attributeCountLabel, (getRowCount() - 1)
0514: * getTagHeight() + LABEL_HEAD_ROOM_SPACE,
0515: SpringLayout.NORTH, this );
0516: //componentList.add(attributeCountLabel);
0517: lastAtribComponent = attributeCountLabel;
0518: }
0519: }
0520:
0521: private void updateAttributeCountLabel() {
0522: int count = getElementPanel().getAXIContainer().getAttributes()
0523: .size();
0524: if (count > 0) {
0525: String hidden = (attributesAreShown) ? "" : " " + locHidden;
0526: String attributeStr = "";
0527: if (!attributesAreShown)
0528: attributeStr = (count == 1) ? " " + locAttr : " "
0529: + locAttrs;
0530:
0531: String str = "[" + count + attributeStr + hidden + "]";
0532: String countStr = "[" + count + "]";
0533: attributeCountLabel.setText(countStr);
0534: attributeCountLabel.setToolTipText(str);
0535: } else {
0536: attributeCountLabel.setText("");
0537: attributeCountLabel.setToolTipText("");
0538: }
0539: }
0540:
0541: protected void addEndSlashLabel() {
0542: add(getEndSlash());
0543: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0544: getEndSlash(), INTER_PANEL_SPACE, SpringLayout.EAST,
0545: lastAtribComponent);
0546: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0547: getEndSlash(), getLastRowComponentsHeadRoom() + 5,
0548: SpringLayout.NORTH, this );
0549: componentList.add(getEndSlash());
0550: lastAtribComponent = getEndSlash();
0551: }
0552:
0553: private int getLastRowComponentsHeadRoom() {
0554: return (getRowCount() - 1)
0555: * (getTagHeight() - TAG_HEIGHT_ADJUSTMENT);
0556: }
0557:
0558: private void addElementPropertiesPanel() {
0559: if (elementPropertiesPanel != null)
0560: excludePaintComponentList.remove(elementPropertiesPanel);
0561: elementPropertiesPanel = getNewAXIContainerPropertiesPanel();
0562: add(elementPropertiesPanel);
0563: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0564: elementPropertiesPanel, getA() + INTER_PANEL_SPACE + 6,
0565: SpringLayout.EAST, getEndSlash());
0566: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0567: elementPropertiesPanel, getLastRowComponentsHeadRoom(),
0568: SpringLayout.NORTH, this );
0569: elementPropertiesPanel.addMouseListener(new MouseAdapter() {
0570: public void mouseClicked(MouseEvent e) {
0571: StartTagPanel.this .dispatchEvent(e);
0572: }
0573:
0574: public void mouseReleased(MouseEvent e) {
0575: StartTagPanel.this .dispatchEvent(e);
0576: }
0577:
0578: public void mousePressed(MouseEvent e) {
0579: StartTagPanel.this .dispatchEvent(e);
0580: }
0581: });
0582: componentList.add(elementPropertiesPanel);
0583: excludePaintComponentList.add(elementPropertiesPanel);
0584: }
0585:
0586: protected void addNonAttributeComponents() {
0587: add(attributeCollapseButton);
0588: attributeCollapseButton.setVisible(false);
0589: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0590: attributeCollapseButton, INTER_PANEL_SPACE,
0591: SpringLayout.EAST, firstRowLastComp);
0592: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0593: attributeCollapseButton, ATTR_HEAD_ROOM_SPACE + 2,
0594: SpringLayout.NORTH, this );
0595: attributeCollapseButton.addActionListener(new ActionListener() {
0596: public void actionPerformed(ActionEvent e) {
0597: showOrHideAttrs();
0598: }
0599: });
0600:
0601: lastAtribComponent = attributeCollapseButton;
0602: addAttributeCountLabel();
0603:
0604: /*//add a hgap between attr collapse button and first tweener.
0605: add(hgap);
0606: startTagPanelLayout.putConstraint(SpringLayout.WEST, hgap,
0607: 0, SpringLayout.EAST, lastAtribComponent);
0608: startTagPanelLayout.putConstraint(SpringLayout.NORTH, hgap,
0609: ATTR_HEAD_ROOM_SPACE, SpringLayout.NORTH, this);*/
0610:
0611: // Add tweener before first attribute..Always
0612: firstTweener = Box.createHorizontalStrut(0);//new TweenerPanel(SwingConstants.VERTICAL, context);
0613: //addTweenerListener(firstTweener);
0614:
0615: add(firstTweener);
0616: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0617: firstTweener, INTER_PANEL_SPACE, SpringLayout.EAST,
0618: lastAtribComponent);
0619: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0620: firstTweener, ATTR_HEAD_ROOM_SPACE, SpringLayout.NORTH,
0621: this );
0622: }
0623:
0624: private void showOrHideAttrs() {
0625: if (attributesAreShown) {
0626: hideAttributes();
0627: } else {
0628: showAttributes();
0629: }
0630:
0631: }
0632:
0633: public void showAttributes() {
0634: if (attributesAreShown)
0635: return;
0636: attributesAreShown = true;
0637: attributeCollapseButton.setText("-");
0638: attributeCountLabel.setVisible(false);
0639: updateAttributes();
0640:
0641: }
0642:
0643: public void hideAttributes() {
0644: if (!attributesAreShown)
0645: return;
0646: attributesAreShown = false;
0647: attributeCollapseButton.setText("+");
0648: attributeCountLabel.setVisible(true);
0649: updateAttributes();
0650: }
0651:
0652: int TAG_HEIGHT_ADJUSTMENT = 5;
0653:
0654: protected void addAttributes() {
0655: int rowCount = 0;
0656: int attrPosition = 0;
0657: Component tweener;
0658: int tagHeight = getTagHeight() - TAG_HEIGHT_ADJUSTMENT;
0659: List<AbstractAttribute> attributeList = getElementPanel()
0660: .getAXIContainer().getAttributes();
0661: for (int i = 0; i < attributeList.size(); i++) {
0662: //calculate the position of this attr
0663: if (i < NO_OF_FIRST_ROW_ATTRS) {
0664: //attr must be in the 1st row
0665: rowCount = 0;
0666: attrPosition = i % NO_OF_FIRST_ROW_ATTRS;
0667: } else {
0668: //these belong to other rows
0669: rowCount = (int) Math
0670: .ceil((double) (i + 1 - NO_OF_FIRST_ROW_ATTRS)
0671: / (double) NO_OF_ATTRS_PER_ROW);
0672: attrPosition = (i + 1 - NO_OF_FIRST_ROW_ATTRS)
0673: % (NO_OF_ATTRS_PER_ROW);
0674: attrPosition--;
0675: if (attrPosition == -1)
0676: attrPosition = NO_OF_ATTRS_PER_ROW - 1;
0677: }
0678:
0679: AttributePanel panel = new AttributePanel(this ,
0680: attributeList.get(i), context);
0681: add(panel);
0682: componentList.add(panel);
0683: if ((attrPosition != 0) || (rowCount == 0)) {
0684: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0685: panel, 0/*INTER_PANEL_SPACE*/,
0686: SpringLayout.EAST, lastAtribComponent);
0687: } else {
0688: //this is first attr
0689: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0690: panel, firstAttrPos, SpringLayout.WEST, this );
0691: }
0692: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0693: panel, rowCount * tagHeight + ATTR_HEAD_ROOM_SPACE
0694: + 1, SpringLayout.NORTH, this );
0695:
0696: tweener = Box.createHorizontalStrut(10);//new TweenerPanel(SwingConstants.VERTICAL, context);
0697: //addTweenerListener(tweener);
0698:
0699: add(tweener);
0700: componentList.add(tweener);
0701: startTagPanelLayout.putConstraint(SpringLayout.WEST,
0702: tweener, 0/*INTER_PANEL_SPACE*/,
0703: SpringLayout.EAST, panel);
0704: startTagPanelLayout.putConstraint(SpringLayout.NORTH,
0705: tweener, rowCount * tagHeight
0706: + ATTR_HEAD_ROOM_SPACE, SpringLayout.NORTH,
0707: this );
0708:
0709: lastAtribComponent = tweener;
0710: if ((i + 1) == NO_OF_FIRST_ROW_ATTRS
0711: && ((i + 1) != attributeList.size())) {
0712: //means first row last element and not last element
0713: firstRowLastComp = lastAtribComponent;
0714: }
0715: }
0716: }
0717:
0718: public int getRowCount() {
0719: int tmprowCount = 0;
0720: if (!attributesAreShown) {
0721: return 1;
0722: }
0723: int atrCount = getElementPanel().getAXIContainer()
0724: .getAttributes().size();
0725: if (atrCount < NO_OF_FIRST_ROW_ATTRS) {
0726: return 1;
0727: } else {
0728: atrCount -= NO_OF_FIRST_ROW_ATTRS;
0729: return (int) Math.ceil((double) atrCount
0730: / (double) NO_OF_ATTRS_PER_ROW) + 1;
0731: }
0732: }
0733:
0734: private void addNewAttributeAt(TweenerPanel tweener) {
0735: int index = componentList.indexOf(tweener);
0736: if (index == -1) {
0737: //must not happen
0738: return;
0739: }
0740: index = index / 2;
0741: AXIContainer element = getElementPanel().getAXIContainer();
0742: AXIModel model = element.getModel();
0743: model.startTransaction();
0744: try {
0745: Attribute attr = model.getComponentFactory()
0746: .createAttribute();
0747: String str = UIUtilities
0748: .getUniqueName(
0749: InstanceDesignConstants.NEW_ATTRIBUTE_NAME,
0750: element);
0751: attr.setName(str);
0752: element.addChildAtIndex(attr, index);
0753: } finally {
0754: model.endTransaction();
0755: }
0756: }
0757:
0758: private void addTweenerListener(final TweenerPanel tweener) {
0759: tweener.addTweenerListener(new TweenerListener() {
0760: public boolean dragAccept(DnDHelper.PaletteItem paletteItem) {
0761: //accept only Attributes
0762: if (paletteItem != DnDHelper.PaletteItem.ATTRIBUTE) {
0763: String str = NbBundle.getMessage(
0764: StartTagPanel.class,
0765: "MSG_ATTRIBUTE_TWEENER_DROP_REJECT");
0766: UIUtilities.showErrorMessageFor(str, context,
0767: StartTagPanel.this );
0768: return false;
0769: }
0770: String str = NbBundle.getMessage(StartTagPanel.class,
0771: "MSG_ATTRIBUTE_TWEENER_DROP_ACCEPT",
0772: getElementPanel().getAXIContainer().getName());
0773: UIUtilities.showBulbMessageFor(str, context,
0774: StartTagPanel.this );
0775: return true;
0776: }
0777:
0778: public void drop(DnDHelper.PaletteItem paletteItem) {
0779: UIUtilities.hideGlassMessage();
0780: addNewAttributeAt(tweener);
0781: }
0782:
0783: public void dragEntered(DnDHelper.PaletteItem paletteItem) {
0784: }
0785:
0786: public void dragExited() {
0787: UIUtilities.hideGlassMessage();
0788: }
0789: });
0790: }
0791:
0792: public int getInterComponentSpacing() {
0793: return INTER_PANEL_SPACE;
0794: }
0795:
0796: public void addElement() {
0797: if (context.isUserInducedEventMode()) {
0798: SwingUtilities.invokeLater(new Runnable() {
0799: public void run() {
0800: getElementPanel().setExpanded(true);
0801: }
0802: });
0803: }
0804: AXIContainer elm = getElementPanel().getAXIContainer();
0805: AXIModel model = elm.getModel();
0806: Compositor comp = elm.getCompositor();
0807: boolean addCompositorFirst = false;
0808: //add a compositor first
0809: //I explicitly start and end transaction to prevent 2 ElementPanels addition in the UI
0810: if (comp == null) {
0811: comp = model.getComponentFactory().createSequence();
0812: addCompositorFirst = true;
0813: }
0814: Element nelm = model.getComponentFactory().createElement();
0815: String str = UIUtilities.getUniqueName(
0816: InstanceDesignConstants.NEW_ELEMENT_NAME, comp);
0817: nelm.setName(str);
0818: try {
0819: model.startTransaction();
0820: if (addCompositorFirst)
0821: elm.addCompositor(comp);
0822: if (comp.getParent() != null && comp.getModel() != null)
0823: comp.addElement(nelm);
0824: } finally {
0825: model.endTransaction();
0826: }
0827: }
0828:
0829: public void addCompositor(Compositor.CompositorType compType) {
0830: AXIContainer elm = getElementPanel().getAXIContainer();
0831: AXIModel model = elm.getModel();
0832: Compositor comp = null;
0833: switch (compType) {
0834: case SEQUENCE:
0835: comp = model.getComponentFactory().createSequence();
0836: break;
0837: case CHOICE:
0838: comp = model.getComponentFactory().createChoice();
0839: break;
0840: case ALL:
0841: comp = model.getComponentFactory().createAll();
0842: break;
0843: }
0844: addCompositor(comp);
0845: }
0846:
0847: public void addCompositor(DnDHelper.PaletteItem compType) {
0848: AXIContainer elm = getElementPanel().getAXIContainer();
0849: AXIModel model = elm.getModel();
0850: Compositor comp = null;
0851: switch (compType) {
0852: case SEQUENCE:
0853: comp = model.getComponentFactory().createSequence();
0854: break;
0855: case CHOICE:
0856: comp = model.getComponentFactory().createChoice();
0857: break;
0858: case ALL:
0859: comp = model.getComponentFactory().createAll();
0860: break;
0861: }
0862: addCompositor(comp);
0863: }
0864:
0865: public void addCompositor(Compositor comp) {
0866: if (comp == null)
0867: return;
0868: AXIContainer elm = getElementPanel().getAXIContainer();
0869: AXIModel model = elm.getModel();
0870:
0871: model.startTransaction();
0872: try {
0873: elm.addCompositor(comp);
0874: } finally {
0875: model.endTransaction();
0876: }
0877: }
0878:
0879: public void addAttribute() {
0880: AXIContainer elm = getElementPanel().getAXIContainer();
0881: AXIModel model = elm.getModel();
0882: model.startTransaction();
0883: try {
0884: Attribute attr = model.getComponentFactory()
0885: .createAttribute();
0886: String str = UIUtilities.getUniqueName(
0887: InstanceDesignConstants.NEW_ATTRIBUTE_NAME, elm);
0888: attr.setName(str);
0889: elm.addAttribute(attr);
0890: } finally {
0891: model.endTransaction();
0892: }
0893: }
0894:
0895: public void drop(DropTargetDropEvent event) {
0896: //hide the bulb message before doing anything
0897: UIUtilities.hideGlassMessage();
0898: if (getElementPanel().getAXIContainer().isReadOnly()) {
0899: event.rejectDrop();
0900: return;
0901: }
0902: setDragMode(false);
0903: context.setUserInducedEventMode(true, this );
0904: try {
0905: super .drop(event);
0906: if (DnDHelper.getDraggedPaletteItem(event) == DnDHelper.PaletteItem.ELEMENT) {
0907: //append the new element
0908: addElement();
0909: }
0910: if (DnDHelper.isCompositor(DnDHelper
0911: .getDraggedPaletteItem(event))) {
0912: if (getElementPanel().getAXIContainer().getCompositor() != null) {
0913: //compositor already added so reject this drop
0914: event.rejectDrop();
0915: return;
0916: } else {
0917: //add a compositor;
0918: addCompositor(DnDHelper
0919: .getDraggedPaletteItem(event));
0920: }
0921: }
0922: if (DnDHelper.getDraggedPaletteItem(event) == DnDHelper.PaletteItem.ATTRIBUTE) {
0923: addAttribute();
0924: }
0925: } finally {
0926: context.setUserInducedEventMode(false);
0927: }
0928: }
0929:
0930: public void dragOver(DropTargetDragEvent event) {
0931: super .dragOver(event);
0932: if (getElementPanel().getAXIContainer().isReadOnly()) {
0933: String str = NbBundle.getMessage(StartTagPanel.class,
0934: "MSG_READONLY_COMPOSITOR_DROP", getElementPanel()
0935: .getAXIContainer().getName());
0936: UIUtilities.showErrorMessageFor(str, context, this );
0937: event.rejectDrag();
0938: return;
0939: }
0940: DnDHelper.PaletteItem item = DnDHelper
0941: .getDraggedPaletteItem(event);
0942: String messageKey = "MSG_ELEMENT_DROP_ACCEPT";
0943: switch (item) {
0944: case ELEMENT:
0945: if (getElementPanel().getAXIContainer() instanceof Element) {
0946: AXIType dt = ((Element) getElementPanel()
0947: .getAXIContainer()).getType();
0948: if (dt != null) {
0949: messageKey = (dt instanceof Datatype) ? "MSG_SIMPLE2COMPLEX_WARNING"
0950: : messageKey;
0951: }
0952: }
0953: case ATTRIBUTE:
0954: String[] options = new String[] {
0955: item.toString().toLowerCase(),
0956: getElementPanel().getAXIContainer().getName() };
0957: String str = NbBundle.getMessage(StartTagPanel.class,
0958: messageKey, options);
0959: UIUtilities.showBulbMessageFor(str, context, this );
0960: return;
0961: case CHOICE:
0962: case SEQUENCE:
0963: case ALL:
0964: if (getElementPanel().getAXIContainer().getCompositor() != null) {
0965: options = new String[] {
0966: getElementPanel().getAXIContainer()
0967: .getCompositor().getType().getName(),
0968: getElementPanel().getAXIContainer().getName() };
0969: //compositor already added so reject this drag
0970: str = NbBundle.getMessage(StartTagPanel.class,
0971: "MSG_ELEMENT_COMPOSITOR_DROP_REJECT", options);
0972: UIUtilities.showErrorMessageFor(str, context, this );
0973: event.rejectDrag();
0974: return;
0975: } else {
0976: options = new String[] { item.toString().toLowerCase(),
0977: getElementPanel().getAXIContainer().getName() };
0978: str = NbBundle.getMessage(StartTagPanel.class,
0979: "MSG_ELEMENT_DROP_ACCEPT", options);
0980: UIUtilities.showBulbMessageFor(str, context, this );
0981: }
0982: return;
0983: default:
0984: options = new String[] { getElementPanel()
0985: .getAXIContainer().getName() };
0986: str = NbBundle.getMessage(StartTagPanel.class,
0987: "MSG_ELEMENT_DROP_REJECT", options);
0988: UIUtilities.showErrorMessageFor(str, context, this );
0989: event.rejectDrag();
0990: return;
0991: }
0992: }
0993:
0994: public void dragEnter(DropTargetDragEvent event) {
0995: super .dragEnter(event);
0996: setDragMode(true);
0997: dragOver(event);
0998: }
0999:
1000: public void dragExit(DropTargetEvent event) {
1001: super .dragExit(event);
1002: setDragMode(false);
1003: UIUtilities.hideGlassMessage();
1004: }
1005:
1006: private void setDragMode(boolean dragMode) {
1007: if (dragMode) {
1008: tagNameLabel.setForeground(Color.WHITE);
1009: expandButton.setDragMode(true);
1010: attributeCollapseButton.setDragMode(true);
1011: } else {
1012: tagNameLabel.setForeground(tagNameLabelColor);
1013: expandButton.setDragMode(false);
1014: attributeCollapseButton.setDragMode(false);
1015: }
1016:
1017: }
1018:
1019: public JLabel getEndSlash() {
1020: endSlash.setVisible(false);
1021: return endSlash;
1022: }
1023:
1024: public void paintComponent(Graphics g) {
1025: Graphics2D g2d = (Graphics2D) g;
1026: super .paintComponent(g2d);
1027:
1028: chainAttributeGroups(g2d);
1029: }
1030:
1031: public JPanel getNewAXIContainerPropertiesPanel() {
1032: return new ElementPropertiesPanel(
1033: (AbstractElement) getElementPanel().getAXIContainer(),
1034: context);
1035: }
1036:
1037: void showTagNameEditor(boolean firstTime) {
1038: this .firstTimeRename = firstTime;
1039: if (tagNameLabel != null)
1040: tagNameLabel.showEditor();
1041: }
1042:
1043: private void addSelectionListener() {
1044: addPropertyChangeListener(new PropertyChangeListener() {
1045: public void propertyChange(PropertyChangeEvent evt) {
1046: if (evt.getPropertyName().equals(PROP_SELECTED)) {
1047: if (((Boolean) evt.getNewValue()).booleanValue()) {
1048: //set the tage name color to orange
1049: //tagNameLabel.setForeground(InstanceDesignConstants.TAG_NAME_SELECTED_COLOR);
1050: Font font = tagNameLabel.getFont();
1051: font = new Font(font.getName(), Font.BOLD, font
1052: .getSize());
1053: tagNameLabel.setFont(font);
1054: getElementPanel().repaint();
1055: } else {
1056: //set the tage name color to normal color
1057: /*tagNameLabel.setForeground(InstanceDesignConstants.TAG_NAME_COLOR);
1058: if(getElementPanel().getAXIContainer().isReadOnly(context.getAXIModel())){
1059: tagNameLabel.setForeground(InstanceDesignConstants.TAG_NAME_READONLY_COLOR);
1060: }else{
1061: if(getElementPanel().getAXIContainer().getContentModel() != null){
1062: //tagNameLabel.setForeground(InstanceDesignConstants.TAG_NAME_SELECTED_COLOR);
1063: }
1064: }*/
1065: Font font = tagNameLabel.getFont();
1066: font = new Font(font.getName(), Font.PLAIN,
1067: font.getSize());
1068: tagNameLabel.setFont(font);
1069: getElementPanel().repaint();
1070: }
1071: getEndSlash().setForeground(
1072: tagNameLabel.getForeground());
1073: getEndSlash().setFont(tagNameLabel.getFont());
1074: }
1075: }
1076: });
1077: }
1078:
1079: protected void chainAttributeGroups(Graphics2D g2d) {
1080: List<AttributePanel> attrPanels = new ArrayList<AttributePanel>();
1081: for (Component comp : componentList) {
1082: if (comp instanceof AttributePanel)
1083: attrPanels.add((AttributePanel) comp);
1084: }
1085: int i = 0;
1086: while (i < attrPanels.size()) {
1087: if (i + 1 < attrPanels.size()) {
1088: chainIfNeeded(attrPanels.get(i), attrPanels.get(i + 1),
1089: g2d);
1090: }
1091: i++;
1092: }
1093: }
1094:
1095: public ABEBaseDropPanel getChildUIComponentFor(
1096: AXIComponent axiComponent) {
1097: if (!(axiComponent instanceof AbstractAttribute)) {
1098: //i deal only with attributes. Rest all element panel should care
1099: return getElementPanel().getChildUIComponentFor(
1100: axiComponent);
1101: }
1102: if (componentList == null)
1103: return null;
1104: showAttributes();
1105: for (Component comp : componentList) {
1106: if (comp instanceof AttributePanel) {
1107: if (((AttributePanel) comp)
1108: .getUIComponentFor(axiComponent) != null) {
1109: return (AttributePanel) comp;
1110: }
1111: }
1112: }
1113: return null;
1114: }
1115:
1116: public List<AttributePanel> getAttributePanels() {
1117: if (componentList == null)
1118: return Collections.EMPTY_LIST;
1119: showAttributes();
1120: List<AttributePanel> result = new ArrayList<AttributePanel>();
1121: for (Component comp : componentList) {
1122: if (comp instanceof AttributePanel) {
1123: result.add((AttributePanel) comp);
1124: }
1125: }
1126: return result;
1127: }
1128:
1129: private void chainIfNeeded(AttributePanel attr1,
1130: AttributePanel attr2, Graphics2D g2d) {
1131: final int L_H_BOX_W = 5;
1132: final int R_H_BOX_W = 10;
1133: final int chainWidth = AttributePanel.getAttributePanelHeight();
1134:
1135: AbstractAttribute at1 = (AbstractAttribute) attr1
1136: .getAXIComponent();
1137: AbstractAttribute at2 = (AbstractAttribute) attr2
1138: .getAXIComponent();
1139:
1140: if (at1.getContentModel() != at2.getContentModel())
1141: return;
1142:
1143: if (at1.getContentModel() == null) {
1144: //both are local attr
1145: return;
1146: }
1147:
1148: if (!at1.isShared()) {
1149: //not an attr grp.
1150: return;
1151: }
1152:
1153: Color fillColor = InstanceDesignConstants.ATTR_BG_SHARED_COLOR;
1154:
1155: if (at1.isReadOnly())
1156: fillColor = InstanceDesignConstants.ATTR_BG_READONLY_COLOR;
1157:
1158: Rectangle r1 = attr1.getBounds();
1159: Rectangle r2 = attr2.getBounds();
1160:
1161: Color oldColor = g2d.getColor();
1162: g2d.setColor(fillColor);
1163:
1164: if (r1.y == r2.y) {
1165: //attrs are next to each other
1166: //draw a horizontal chain
1167: int x, y, width, height;
1168: x = r1.x + r1.width;
1169: y = r1.y + (r1.height - chainWidth) / 2;
1170: width = r2.x - x;
1171: height = chainWidth;
1172: //g2d.drawRect( x, y, width, height);
1173: g2d.fillRect(x, y, width, height);
1174: } else {
1175: //attrs are not in the same line
1176:
1177: //draw right broken attr tape
1178: int xfudge = 8;
1179:
1180: Point pt = new Point(r1.x + r1.width + xfudge, r1.y);
1181: List<Point> plist = UIUtilities.getBrokenTapePoints(pt,
1182: r1.y + r1.height - 1, 5, 4, true);
1183: Polygon rightTape = new Polygon();
1184: for (Point tpt : plist) {
1185: rightTape.addPoint(tpt.x, tpt.y);
1186: }
1187: rightTape.addPoint(r1.x + r1.width, r1.y + r1.height - 1);
1188: rightTape.addPoint(r1.x + r1.width, r1.y);
1189: g2d.draw(rightTape);
1190: g2d.fill(rightTape);
1191:
1192: //draw left broken attr tape
1193: xfudge -= 3;
1194: pt = new Point(r2.x - xfudge, r2.y);
1195: plist = UIUtilities.getBrokenTapePoints(pt, r2.y
1196: + r2.height - 1, 5, 4, false);
1197: Polygon leftTape = new Polygon();
1198: for (Point tpt : plist) {
1199: leftTape.addPoint(tpt.x, tpt.y);
1200: }
1201: leftTape.addPoint(r2.x, r2.y + r2.height - 1);
1202: leftTape.addPoint(r2.x, r2.y);
1203: g2d.draw(leftTape);
1204: g2d.fill(leftTape);
1205: }
1206: g2d.setColor(oldColor);
1207: }
1208:
1209: public void accept(UIVisitor visitor) {
1210: visitor.visit(this );
1211: }
1212:
1213: ////////////////////////////////////////////////////////////////////////////
1214: // Instance members
1215: ////////////////////////////////////////////////////////////////////////////
1216:
1217: private InplaceEditableLabel tagNameLabel;
1218:
1219: List<Component> componentList;
1220: private Component firstTweener;
1221:
1222: private static final int ATTR_HEAD_ROOM_SPACE = 3;
1223: private static final int LABEL_HEAD_ROOM_SPACE = (TagPanel
1224: .getTagHeight() / 2) - 9;
1225: private static final int INTER_PANEL_SPACE = 2;
1226:
1227: private final JLabel endSlash = new JLabel("");
1228: private JPanel elementPropertiesPanel;
1229: RoundExpandCollapseButton attributeCollapseButton = new RoundExpandCollapseButton(
1230: "+", false);
1231: boolean attributesAreShown = false;
1232: JLabel attributeCountLabel = new JLabel();
1233: public static final int NO_OF_FIRST_ROW_ATTRS = 5;
1234: public static final int NO_OF_ATTRS_PER_ROW = 6;
1235: int firstAttrPos = getA() + INTER_PANEL_SPACE + 12;
1236: JLabel hgap = new JLabel();
1237: }
|