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.uml.ui.controls.editcontrol;
0043:
0044: import java.awt.Dimension;
0045: import java.awt.Font;
0046: import java.awt.Toolkit;
0047: import java.awt.datatransfer.Clipboard;
0048: import java.awt.datatransfer.DataFlavor;
0049: import java.awt.datatransfer.StringSelection;
0050: import java.awt.datatransfer.Transferable;
0051: import java.awt.datatransfer.UnsupportedFlavorException;
0052: import java.awt.event.KeyEvent;
0053: import java.io.IOException;
0054: import java.lang.reflect.Array;
0055: import java.lang.reflect.Constructor;
0056: import java.util.Arrays;
0057: import java.util.Collection;
0058: import java.util.Vector;
0059:
0060: import org.netbeans.modules.uml.common.generics.ETPairT;
0061: import org.netbeans.modules.uml.core.coreapplication.ICoreProduct;
0062: import org.netbeans.modules.uml.core.eventframework.IEventDispatcher;
0063: import org.netbeans.modules.uml.core.metamodel.core.foundation.IConfigManager;
0064: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
0065: import org.netbeans.modules.uml.core.metamodel.core.foundation.INamedElement;
0066: import org.netbeans.modules.uml.core.metamodel.core.foundation.INamespace;
0067: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IOperation;
0068: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IOperationSignatureChangeContextManager;
0069: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.OperationSignatureChangeContextManager;
0070: import org.netbeans.modules.uml.core.metamodel.structure.IProject;
0071: import org.netbeans.modules.uml.core.support.umlsupport.IStrings;
0072: import org.netbeans.modules.uml.core.support.umlsupport.Log;
0073: import org.netbeans.modules.uml.core.support.umlsupport.ProductRetriever;
0074: import org.netbeans.modules.uml.core.support.umlsupport.Strings;
0075: import org.netbeans.modules.uml.core.support.umlutils.ETList;
0076: import org.netbeans.modules.uml.core.support.umlutils.IDataFormatter;
0077: import org.netbeans.modules.uml.core.support.umlutils.IPropertyDefinition;
0078: import org.netbeans.modules.uml.core.support.umlutils.IPropertyDefinitionFactory;
0079: import org.netbeans.modules.uml.core.support.umlutils.IPropertyElement;
0080: import org.netbeans.modules.uml.core.support.umlutils.IPropertyElementManager;
0081: import org.netbeans.modules.uml.core.support.umlutils.PropertyDefinitionFactory;
0082: import org.netbeans.modules.uml.core.support.umlutils.PropertyElementManager;
0083: import org.netbeans.modules.uml.core.typemanagement.IPickListManager;
0084: import org.netbeans.modules.uml.core.typemanagement.ITypeManager;
0085: import org.netbeans.modules.uml.ui.support.ProductHelper;
0086: import org.netbeans.modules.uml.ui.support.applicationmanager.IProduct;
0087: import org.netbeans.modules.uml.ui.support.applicationmanager.IProductProjectManager;
0088:
0089: /**
0090: * @author sumitabhk
0091: *
0092: */
0093: public class TranslatorImpl implements ITranslator {
0094: // state attributes, used with AxEditCtrl
0095: private String m_RawString = "";
0096: private String m_FormattedString = "";
0097: private IEditControl m_EditControl = null;
0098: private IElement m_Element = null;
0099: private Vector m_TextFields = null;
0100: private boolean m_Modified = false;
0101:
0102: /// The formatter object that will eventually replace all these other members
0103: private IPropertyDefinitionFactory m_DefinitionFactory = null;
0104: private IPropertyElementManager m_ElementManager = null;
0105: private IEditControlField m_ParentField = null;
0106: private IPropertyElement m_PropertyElement = null;
0107:
0108: private String m_TooltipLeftText = "";
0109: private String m_TooltipSubjectText = "";
0110: private String m_TooltipRightText = "";
0111: private boolean m_IsGetToolTipText = false;
0112:
0113: // prevent recursion
0114: private boolean m_InSet = false;
0115:
0116: /**
0117: *
0118: */
0119: public TranslatorImpl() {
0120: super ();
0121: }
0122:
0123: /**
0124: * Gets/Sets the model element.
0125: *
0126: * @param pElement[out]
0127: */
0128: public IElement getElement() {
0129: return m_Element;
0130: }
0131:
0132: /**
0133: * Gets/Sets the model element.
0134: *
0135: * @param pElement[in]
0136: */
0137: public void setElement(IElement pElement) {
0138: m_Element = pElement;
0139: }
0140:
0141: /**
0142: * Returns the EditControl reference.
0143: *
0144: * @param pControl[out] The edit control associated with this editing session.
0145: */
0146: public IEditControl getEditControl() {
0147: IEditControl retObj = null;
0148:
0149: if (m_EditControl == null) {
0150: if (m_ParentField != null) {
0151: ITranslator pTranslator = m_ParentField
0152: .getOwnerTranslator();
0153: if (pTranslator != null) {
0154: m_EditControl = pTranslator.getEditControl();
0155: if (m_EditControl != null) {
0156: // Since m_EditControl is a raw pointer to avoid deadly
0157: // embraces we do a manual release so we don't leak
0158: // a refcount.
0159: //m_EditControl.removeReference();
0160: }
0161: }
0162: }
0163: }
0164:
0165: if (m_EditControl != null) {
0166: retObj = m_EditControl;
0167: // Since m_EditControl is a raw pointer we do a manual
0168: // addref so the out parameter is safely returned, as would
0169: // be the case if m_EditControl was a CComPtr and we called
0170: // CopyTo.
0171: // _VH(m_EditControl->AddRef());
0172: }
0173:
0174: return retObj;
0175: }
0176:
0177: /**
0178: * Sets the AxEditCtrl, called prior to editing. The text fields are initialized and the
0179: * edit control's window set to the current contents of this Translator.
0180: *
0181: * @param pControl A pointer to the edit control that uses this Translator. If NULL or 0
0182: * the fields are initialized anyway (assuming an Element has been attached).
0183: */
0184: public void setEditControl(IEditControl pControl) {
0185: m_EditControl = pControl;
0186:
0187: setCurrentPosition(0);
0188:
0189: try {
0190: // here's where we should perform the parsing:
0191: initTextFields();
0192:
0193: // update the control's display
0194: refreshEditControl();
0195: } catch (Exception e) {
0196: Log.stackTrace(e);
0197: }
0198: }
0199:
0200: /**
0201: * Sets the AxEditCtrl only, does not perform any initialization.
0202: *
0203: * @param pControl A pointer to the edit control that uses this Translator..
0204: */
0205: public void setEditControl2(IEditControl pControl) {
0206: m_EditControl = pControl;
0207:
0208: if (m_EditControl != null) {
0209: IEditControlField pField = null;
0210: while ((pField = getNextField(pField)) != null) {
0211: ITranslator pTranslator = pField.getTranslator();
0212: if (pTranslator != null) {
0213: pTranslator.setEditControl2(m_EditControl);
0214: }
0215: }
0216: }
0217: }
0218:
0219: /**
0220: * Get a formatted string. The data is from the model and may not reflect any
0221: * un-saved changes made via editing.
0222: *
0223: * C++ Specifications : visibility return-type-expression name ( parameter-list )
0224: * UML Specifications : visibility name ( parameter-list ) : return-type-expression { property-string }
0225: *
0226: * For the sake of the simple format the optional property string will not be returned.
0227: */
0228: public String getSimple() {
0229: String retStr = "";
0230: if (m_Element != null) {
0231: IDataFormatter pFormatter = ProductHelper
0232: .getDataFormatter();
0233: if (pFormatter != null) {
0234: retStr = pFormatter.formatElement(m_Element);
0235: }
0236: }
0237: return retStr;
0238: }
0239:
0240: /**
0241: * Builds up the display string by concatenating each visible field.
0242: * You must call InitTextFields() before calling get_Current() to
0243: * create and fill each text field. InitTextFields() a protected
0244: * member of TranslatorImpl, if you need to call InitTextFields()
0245: * via COM call put_EditControl().
0246: *
0247: * @param pVal[out]
0248: */
0249: public String getCurrent() {
0250: String retStr = "";
0251: String sDelimiter = null;
0252: if (m_ParentField != null) {
0253: sDelimiter = m_ParentField.getDelimitor();
0254: }
0255:
0256: boolean bFirst = false;
0257: IEditControlField pField = getNextVisibleField(null);
0258: while (pField != null) {
0259: boolean bDeleted = pField.getDeleted();
0260: String str = "";
0261: if (!bDeleted) {
0262: if (bFirst) {
0263: if (sDelimiter != null) {
0264: str = sDelimiter;
0265: }
0266: } else {
0267: bFirst = true;
0268: }
0269:
0270: String sTemp = "";
0271: if (pField.getLeadSeparator() != null) {
0272: sTemp = pField.getLeadSeparator();
0273: }
0274: str += sTemp;
0275:
0276: sTemp = "";
0277: if (pField.getText() != null) {
0278: sTemp = pField.getText();
0279: }
0280: str += sTemp;
0281:
0282: sTemp = "";
0283: if (pField.getTrailSeparator() != null) {
0284: sTemp = pField.getTrailSeparator();
0285: }
0286: str += sTemp;
0287:
0288: retStr += str;
0289: }
0290: pField = getNextVisibleField(pField);
0291: }
0292: return retStr;
0293: }
0294:
0295: /*
0296: * Makes the field visible, fills with default data if available.
0297: *
0298: * @param pField[in]
0299: */
0300: private void insureVisibleAndNotEmpty(IEditControlField pField) {
0301: if (pField != null) {
0302: String str = pField.getText();
0303: if (str == null || str.length() == 0) {
0304: // no text, get the default text since we're insuring not empty
0305: pField.setDefaultText();
0306: }
0307: setFieldVisible(pField, true);
0308: }
0309: }
0310:
0311: /**
0312: * Returns a TextField collection representing each field in the translated string.
0313: *
0314: * @param pFields[out]
0315: */
0316: public Vector getTextFields() {
0317: if (m_TextFields == null) {
0318: m_TextFields = new Vector();
0319: }
0320: return m_TextFields;
0321: }
0322:
0323: /**
0324: * Gets the caret position, called by the edit control.
0325: *
0326: * @param nPos[in]
0327: */
0328: public int getPosition() {
0329: if (m_EditControl != null) {
0330: return m_EditControl.getCurrentPosition();
0331: }
0332: return 0;
0333: }
0334:
0335: /**
0336: * Sets the caret position, called by the edit control.
0337: *
0338: * @param nPos[out]
0339: */
0340: public void setPosition(int pos) {
0341: setPosition(pos, pos);
0342: }
0343:
0344: /**
0345: * Returns the starting and ending position of the editable text contained by this Translator. The
0346: * position is the offset within the edit control.
0347: *
0348: * @param[out] nStartPos The offset from the first character in the edit control to the first
0349: * character in the first textfield contained by this Translator.
0350: * @param[out] nEndPos The offset from the first character in the edit control to the last
0351: * character in the last textfield contained by this Translator.
0352: *
0353: * @return HRESULT
0354: */
0355: public void getTextPos(int nStartPosition, int nEndPosition) {
0356: int dummy = 0;
0357: // read first field, obtain starting position
0358: IEditControlField pField = getNextField(null);
0359: if (pField != null) {
0360: nStartPosition = pField.getTextStartPos();
0361: nEndPosition = pField.getTextEndPos();
0362: }
0363:
0364: // loop until no more visible fields, updating ending position
0365: while ((pField = getNextField(pField)) != null) {
0366: nEndPosition = pField.getTextEndPos();
0367: }
0368: }
0369:
0370: /**
0371: * Returns the starting and ending position of the textfields contained by this Translator. The
0372: * position is the offset within the edit control.
0373: *
0374: * @param[out] nStartPos The offset from the first character in the edit control to the first
0375: * character in the first textfield contained by this Translator.
0376: * @param[out] nEndPos The offset from the first character in the edit control to the last
0377: * character in the last textfield contained by this Translator.
0378: *
0379: * @return HRESULT
0380: */
0381: public void getFieldPos(int nStartPosition, int nEndPosition) {
0382: IEditControlField pField = getNextField(null);
0383: if (pField != null) {
0384: nStartPosition = pField.getFieldStartPos();
0385: nEndPosition = pField.getFieldEndPos();
0386: // hidden fields will return nStartPos == nEndPos so account for no text width
0387: int dummy = 0;
0388: while ((pField = getNextField(pField)) != null) {
0389: nEndPosition = pField.getFieldEndPos();
0390: }
0391: }
0392: }
0393:
0394: /**
0395: * Sets the position of the fields contained by this translator to the edit control position indicated.
0396: * Ordinarily a Translator's first field always starts at edit position 0, however in the case
0397: * of sub-fields they could be different.
0398: *
0399: * @param[in] nStartPos The new starting position. All fields will be moved accordingly
0400: *
0401: * @return HRESULT
0402: */
0403: public void setFieldPos(int nStartPosition) {
0404: String delimiter = "";
0405: if (m_ParentField != null) {
0406: delimiter = m_ParentField.getDelimitor();
0407: }
0408:
0409: boolean bFirst = false;
0410: int nDelimSpace = 0;
0411:
0412: IEditControlField pField = getNextField(null);
0413: while (pField != null) {
0414: if (bFirst) {
0415: if (delimiter != null) {
0416: nDelimSpace = delimiter.length();
0417: }
0418: } else {
0419: bFirst = true;
0420: }
0421:
0422: int dummy = 0;
0423: boolean deleted = pField.getDeleted();
0424: if (!deleted) {
0425: pField.setFieldPos(nStartPosition + nDelimSpace);
0426: } else {
0427: pField.setFieldPos(nStartPosition);
0428: }
0429:
0430: nStartPosition = pField.getFieldEndPos();
0431: pField = getNextField(pField);
0432: }
0433: }
0434:
0435: /**
0436: * Sets the edit control's cursor position and selects text.
0437: */
0438: public void setPosition(int nStartPos, int nEndPos) {
0439: if (m_EditControl != null) {
0440: m_EditControl.setSel(nStartPos, nEndPos);
0441: m_EditControl.getSel(nStartPos, nEndPos);
0442: m_EditControl.setCurrentPosition(nEndPos);
0443: }
0444: setCurrentPosition(nEndPos);
0445: updateHints();
0446: }
0447:
0448: /* (non-Javadoc)
0449: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#handleKeyDown(int)
0450: */
0451: public boolean handleKeyDown(int nKey) {
0452: boolean handled = false;
0453: IEditControlField pField = getCurrentField();
0454: int nStart = 0;
0455: int nEnd = 0;
0456: int nStartPos = 0;
0457: int nEndPos = 0;
0458: int nNext = 0;
0459:
0460: // get current field and offsets
0461: if (pField == null) {
0462: return false;
0463: }
0464: nStart = pField.getTextStartPos();
0465: nEnd = pField.getTextEndPos();
0466:
0467: // get selected area
0468: nStartPos = getSelStartPos();
0469: nEndPos = getSelEndPos();
0470:
0471: // if field contains sub-fields, delegate
0472: ITranslator pTrans = pField.getTranslator();
0473: if (pTrans != null) {
0474: // don't attempt to catch
0475: handled = pTrans.handleKeyDown(nKey);
0476: if (handled) {
0477: return true;
0478: }
0479: }
0480:
0481: if (nKey == KeyEvent.VK_RIGHT) {
0482: // special situation, when text is selected the edit control always places the caret at the end
0483: nNext = getCurrentPosition() + 1;
0484:
0485: // if text is selected we may need to provide special handling
0486: if (nStartPos != nEndPos) {
0487: // if shift is not down, dismiss the selection and
0488: // put the cursor at the right edge
0489: if (!shiftDown()) {
0490: selectToPosition(nEndPos);
0491: return true;
0492: }
0493: }
0494:
0495: if (controlDown()) {
0496: // control down, doing a jump
0497: // default is to jump to the end of the current field
0498: nNext = (nNext > nEnd) ? nNext : nEnd;
0499: }
0500:
0501: if (nNext > nEnd) {
0502: pField = getNextVisibleField(pField);
0503: }
0504: if (pField == null) {
0505: // no more fields, we're done
0506: return false;
0507: }
0508:
0509: // jump to front of next field
0510: // don't let them land on separator text
0511: nStart = pField.getTextStartPos();
0512: nEnd = pField.getTextEndPos();
0513: if (nNext < nStart) {
0514: nNext = nStart;
0515: } else if (nNext > nEnd) {
0516: int edge = 0;
0517:
0518: // we're stepping over a trailing separator
0519: nStart = pField.getFieldStartPos();
0520: edge = pField.getFieldEndPos();
0521:
0522: // skip over the separator by setting our current position to the
0523: // end of the separator and recursing
0524:
0525: // move past our field, check for another
0526: IEditControlField pNextField = getNextVisibleField(pField);
0527: if (pNextField != null) {
0528: edge = pNextField.getTextStartPos();
0529: nEnd = pNextField.getTextEndPos();
0530: }
0531:
0532: setSel(edge, edge);
0533: updateHints();
0534: return true;
0535: }
0536:
0537: // move caret, honoring selection mode
0538: selectToPosition(nNext);
0539: updateVisibleFields(null);
0540: return true;
0541: } else if (nKey == KeyEvent.VK_LEFT) {
0542: // already at left, nothing to do
0543: if (getCurrentPosition() == 0) {
0544: return true;
0545: }
0546:
0547: // calc position to go to
0548: nNext = getCurrentPosition() - 1;
0549:
0550: // if text is selected we may need to provide special handling
0551: if (nStartPos != nEndPos) {
0552: // text is selected and we're going left
0553: // if shift is not down, dismiss the selection and
0554: // put the cursor at the left edge
0555: if (!shiftDown()) {
0556: selectToPosition(nStartPos);
0557: return true;
0558: }
0559: }
0560:
0561: // are we jumping?
0562: if (controlDown()) {
0563: // jump to front of current field unless already there
0564: nNext = (nNext < nStart) ? nNext : nStart;
0565: }
0566:
0567: // if we've passed our field
0568: if (nNext < nStart) {
0569: IEditControlField pNextField = getPreviousVisibleField(pField);
0570:
0571: // no visible fields to the left?
0572: // there might be some hidden ones, try getting it
0573: if (pNextField == null) {
0574: pField = getPreviousField(pField);
0575: } else {
0576: pField = pNextField;
0577: }
0578: }
0579: if (pField == null) {
0580: return false;
0581: }
0582:
0583: // don't let them land on separator text
0584: nStart = pField.getTextStartPos();
0585: nEnd = pField.getTextEndPos();
0586: if (nNext > nEnd) {
0587: nNext = nEnd;
0588: } else if (nNext < nStart) {
0589: int edge = getCurrentPosition();
0590:
0591: // we're stepping over a trailing separator
0592: edge = pField.getFieldStartPos();
0593: nEnd = pField.getFieldEndPos();
0594:
0595: // skip over the separator by setting our current position to the
0596: // end of the separator and recursing
0597:
0598: // move past our field, check for another
0599: IEditControlField pNextField = getPreviousVisibleField(pField);
0600: if (pNextField != null) {
0601: nStart = pNextField.getTextStartPos();
0602: edge = pNextField.getTextEndPos();
0603: }
0604: setSel(edge, edge);
0605: return true;
0606: } else {
0607: // are we jumping?
0608: if (controlDown()) {
0609: // jump to front of current field unless already there
0610: nNext = (nNext < nStart) ? nNext : nStart;
0611: }
0612: }
0613:
0614: // move caret, honoring selection mode
0615: selectToPosition(nNext);
0616: updateVisibleFields(null);
0617: return true;
0618: } else if (nKey == KeyEvent.VK_TAB) {
0619: if (shiftDown()) {
0620: // going left, if current position is at the end of our field select it
0621: if (getCurrentPosition() >= nEnd) {
0622: selectField(pField);
0623: } else {
0624: // jumping leftwards, find next editable field
0625: IEditControlField pPrevField = getPreviousVisibleField(pField);
0626: if (pPrevField != null) {
0627: ITranslator pPrevTrans = pPrevField
0628: .getTranslator();
0629: if (pPrevTrans != null) {
0630: // has a translator we want to jump to the last visible field
0631: jumpToFieldEnd(pPrevField);
0632: handled = handleKeyDown(nKey);
0633: return handled;
0634: } else {
0635: // no translator, select it and we're outta here
0636: selectField(pPrevField);
0637: }
0638: } else {
0639: // no more fields, set position then let the control handle it
0640: if (getCurrentPosition() > 0) {
0641: jumpToFieldBegin(pField);
0642: updateVisibleFields(m_ParentField);
0643: return true;
0644: }
0645: }
0646: }
0647: } else {
0648: // jumping rightwards, find next editable field
0649: IEditControlField pNextField = getNextVisibleField(pField);
0650: if (pNextField != null) {
0651: selectField(pNextField);
0652: } else {
0653: handled = handleEndKeyDown();
0654: return handled;
0655: }
0656: }
0657: handled = true;
0658: updateVisibleFields(m_ParentField);
0659: } else if (nKey == KeyEvent.VK_DELETE) {
0660: handled = handleDelete(true);
0661: } else if (nKey == KeyEvent.VK_BACK_SPACE) {
0662: handled = handleDelete(false);
0663: }
0664: return handled;
0665: }
0666:
0667: public boolean handleEndKeyDown() {
0668: boolean handled = false;
0669: int pos = getCurrentPosition();
0670: updateVisibleFields(m_ParentField);
0671: setPosition(pos);
0672: return handled;
0673: }
0674:
0675: /* (non-Javadoc)
0676: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#handleKeyUp(int)
0677: */
0678: public boolean handleKeyUp(int nKey) {
0679: // TODO Auto-generated method stub
0680: return false;
0681: }
0682:
0683: /**
0684: * Process WM_CHAR for translated input.
0685: *
0686: * @param nChar[in]
0687: * @param bHandled[out]
0688: */
0689: public boolean handleChar(String nChangedChar) {
0690: boolean isHandled = false;
0691: try {
0692: IEditControlField pField = null;
0693:
0694: // apply default filtering
0695: if (nChangedChar.length() > 0
0696: && filterChar(nChangedChar.charAt(0))) {
0697: // character is filtered, ignore it
0698: isHandled = false;
0699: return isHandled;
0700: }
0701:
0702: // get current field and offsets
0703: pField = getCurrentField();
0704: if (pField != null) {
0705: boolean bVisible = pField.getVisible();
0706: boolean bEnabled = pField.getEnabled();
0707:
0708: // current field may not be enabled if it is empty
0709: if (!bEnabled) {
0710: // enable all field contained by this translator
0711: pField.setEnabled(true);
0712: }
0713:
0714: bVisible = pField.getVisible();
0715: if (!bVisible) {
0716: // we don't want to just set visible b/c this forces the visiblity to TRUE (overrides the field's
0717: // visibility rules) Only force it true if this is the active field and it isn't visible currently
0718: pField.setVisible(true);
0719: }
0720:
0721: // if field contains sub-fields, delegate
0722: ITranslator pTranslator = pField.getTranslator();
0723: if (pTranslator != null) {
0724: // don't attempt to catch
0725: // key down, insert it at the current position
0726: isHandled = pTranslator.handleChar(nChangedChar);
0727: }
0728:
0729: int nStartPos = getSelStartPos();
0730: int nEndPos = getSelEndPos();
0731:
0732: int nStart = pField.getTextStartPos();
0733: int nEnd = pField.getTextEndPos();
0734:
0735: String sText = nChangedChar;
0736:
0737: // anything selected?
0738: if (nStartPos != nEndPos) {
0739: // here we try to determine if the selected area crosses field boundaries
0740: IEditControlField pNextField = pField;
0741: while (nEndPos > nEnd) {
0742: // move past our field, check for another
0743: pNextField = getNextVisibleField(pNextField);
0744: if (pNextField == null) {
0745: // no more fields, insert here
0746: nEndPos = nStartPos;
0747: break;
0748: } else {
0749: // fetch the field's boundaries
0750: nStart = pNextField.getTextStartPos();
0751: nEnd = pNextField.getTextEndPos();
0752:
0753: if (nEndPos >= nEnd) {
0754: pNextField.setText("");
0755: pNextField.setVisible(false);
0756: } else {
0757: break;
0758: }
0759: }
0760: }
0761: // should have our insert position worked out
0762: setModified(true);
0763: } else {
0764: boolean bOverstrike = false;
0765: if (m_EditControl != null) {
0766: bOverstrike = m_EditControl.getOverstrike();
0767: }
0768: if (bOverstrike) {
0769: // nothing selected but in overstrike mode so select
0770: // next char to replace
0771: nEndPos = nStartPos + 1;
0772:
0773: if (nEndPos > nEnd) {
0774: // move past our field, check for another
0775: IEditControlField pNextField = getNextVisibleField(pField);
0776: if (pNextField == null) {
0777: // no more fields, insert here
0778: nEndPos = nStartPos;
0779: }
0780: }
0781: } else {
0782: // nothing selected and not in overstrike
0783: // just insert at the current position
0784: nEndPos = nStartPos;
0785: }
0786: }
0787:
0788: // replace selection with the char
0789: // save current position for restore afterwards
0790: replaceText(pField, nStartPos, nEndPos, sText, true);
0791: isHandled = true;
0792: }
0793: } catch (Exception e) {
0794: Log.stackTrace(e);
0795: }
0796: return isHandled;
0797: }
0798:
0799: private int getSelStartPos() {
0800: if (m_EditControl != null) {
0801: return m_EditControl.getSelStartPos();
0802: } else {
0803: // can't simulate selection if no edit control
0804: return getCurrentPosition();
0805: }
0806: }
0807:
0808: private int getSelEndPos() {
0809: if (m_EditControl != null) {
0810: return m_EditControl.getSelEndPos();
0811: } else {
0812: // can't simulate selection if no edit control
0813: return getCurrentPosition();
0814: }
0815: }
0816:
0817: /**
0818: * Identifies the allowed characters for edit control.
0819: * @param nChar
0820: * @return
0821: */
0822: private boolean filterChar(char nChar) {
0823: boolean isFiltered = true;
0824:
0825: //right now we allow only alpha numeric, _, : and blank
0826: if (Character.isLetterOrDigit(nChar)) {
0827: isFiltered = false;
0828: } else {
0829: //if control key is pressed then we want to filter the character.
0830: if (m_EditControl != null && !m_EditControl.isControlDown()) {
0831: isFiltered = false;
0832: }
0833: }
0834: return isFiltered;
0835: }
0836:
0837: /* (non-Javadoc)
0838: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#handleLButtonDown(int)
0839: */
0840: public boolean handleLButtonDown(int nPosition) {
0841: // TODO Auto-generated method stub
0842: return false;
0843: }
0844:
0845: /* (non-Javadoc)
0846: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#handleLButtonDblClk(int)
0847: */
0848: public boolean handleLButtonDblClk(int nPosition) {
0849: // TODO Auto-generated method stub
0850: return false;
0851: }
0852:
0853: /* (non-Javadoc)
0854: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#handleLButtonTripleClk(int)
0855: */
0856: public boolean handleLButtonTripleClk(int nPosition) {
0857: // TODO Auto-generated method stub
0858: return false;
0859: }
0860:
0861: /**
0862: * Called when the control is initially activated. Selects the first entire field for editing.
0863: */
0864: public void onSetFocus() {
0865: IEditControlField pField = getDefaultField();
0866: if (pField != null) {
0867: selectField(pField);
0868: } else {
0869: int startPos = getTextStartPos();
0870: int endPos = getTextEndPos();
0871: //getTextPos(startPos, endPos);
0872: setPosition(startPos);
0873: }
0874: }
0875:
0876: /**
0877: * Save the model element.
0878: *
0879: * DO NOT RECURSE! This member is called by the edit control only.
0880: */
0881: public void saveModelElement() {
0882: if (m_EditControl == null) {
0883: return;
0884: }
0885:
0886: boolean proceed = true;
0887: proceed = getModified();
0888:
0889: if (proceed) {
0890: // The event dispatcher
0891: IEventDispatcher pDispatcher = null;
0892: IEditEventPayload payload = null;
0893:
0894: // try to get the edit control's event dispatcher
0895: if (m_EditControl != null) {
0896: pDispatcher = m_EditControl.getEventDispatcher();
0897: }
0898:
0899: IEditControlEventDispatcher pEventDispatcher = null;
0900: // if we got a dispatcher fire precommit
0901: if (pDispatcher != null
0902: && pDispatcher instanceof IEditControlEventDispatcher) {
0903: pEventDispatcher = (IEditControlEventDispatcher) pDispatcher;
0904: payload = pEventDispatcher.createEventPayload();
0905: proceed = pEventDispatcher.firePreCommit(payload);
0906: }
0907:
0908: // precommit not fired or fired/return proceed
0909: if (proceed) {
0910: saveFields();
0911: m_Modified = false;
0912: }
0913:
0914: if (pEventDispatcher != null) {
0915: pEventDispatcher.firePostCommit(payload);
0916: }
0917: m_EditControl = null;
0918: }
0919: }
0920:
0921: /**
0922: * Updates the translator's internal position pointer without affecting the edit control. To update
0923: * the position pointer and move the edit control cursor caret use Position();
0924: *
0925: * @param[in] nPos The new position of the control insertion point.
0926: *
0927: * @return HRESULT
0928: */
0929: public void setCurrentPosition(int nPos) {
0930: if (m_EditControl != null) {
0931: m_EditControl.setCurrentPosition(nPos);
0932: }
0933: }
0934:
0935: /**
0936: *
0937: * Turns field visibility override off. Thus the field's visibility within the edit control is dictated by its
0938: * visibility settings, e.g. notEmpty, enabled, not deleted, etc.
0939: *
0940: * @param pField [in] The field to set. If NULL all fields contained by this translator are set.
0941: *
0942: * @return HRESULT
0943: *
0944: */
0945: public void updateVisibleFields(IEditControlField pField) {
0946: if (pField != null) {
0947: // a specific field has been targeted, set its visibility override to false
0948: pField.setVisible(false);
0949:
0950: ITranslator translator = pField.getTranslator();
0951: if (translator != null) {
0952: translator.updateVisibleFields(null);
0953: }
0954: } else {
0955: // walk the fields
0956: pField = getLastField();
0957: while (pField != null) {
0958: updateVisibleFields(pField);
0959: pField = getPreviousField(pField);
0960: }
0961: }
0962: }
0963:
0964: /**
0965: *
0966: * Returns the text field at a given character position.
0967: *
0968: * @param nPos[in] The zero-based character position
0969: *
0970: * @return The text field at that position
0971: *
0972: */
0973: private IEditControlField getFieldAtPosition(int nPos) {
0974: IEditControlField pField = null;
0975: int nStart = 0, nEnd = 0;
0976: while ((pField = getNextField(pField)) != null) {
0977: nStart = pField.getFieldStartPos();
0978: nEnd = pField.getFieldEndPos();
0979: if (nStart <= nPos && nPos <= nEnd)
0980: break;
0981: }
0982: return pField;
0983: }
0984:
0985: /* (non-Javadoc)
0986: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#cutToClipboard()
0987: */
0988: public void cutToClipboard() {
0989: if (null == m_EditControl)
0990: return;
0991:
0992: IEditControlField field = getCurrentField();
0993:
0994: // get current field and offsets
0995: if (field != null) {
0996: int nStartPos = getSelStartPos();
0997: int nEndPos = getSelEndPos();
0998:
0999: int nStart = field.getTextStartPos();
1000: int nEnd = field.getTextEndPos();
1001:
1002: // can't cut across field boundaries
1003: if ((nStartPos < nStart) || (nEndPos > nEnd)) {
1004: // TODO messageBeep( MB_ICONASTERISK );
1005: return;
1006: } else {
1007: if (nStartPos != nEndPos) {
1008: String str = m_EditControl.getText();
1009:
1010: Transferable transferable = new StringSelection(str
1011: .substring(nStartPos, nEndPos));
1012:
1013: Toolkit.getDefaultToolkit().getSystemClipboard()
1014: .setContents(transferable, null);
1015: replaceText(field, nStartPos, nEndPos, "", true);
1016: }
1017: }
1018: }
1019: }
1020:
1021: /* (non-Javadoc)
1022: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#pasteFromClipboard()
1023: */
1024: public void pasteFromClipboard() {
1025: IEditControlField field = getCurrentField();
1026:
1027: // get current field and offsets
1028: if (field != null) {
1029: int nStartPos = getSelStartPos();
1030: int nEndPos = getSelEndPos();
1031:
1032: int nStart = field.getTextStartPos();
1033: int nEnd = field.getTextEndPos();
1034:
1035: // can't paste across field boundaries
1036: if ((nStartPos < nStart) || (nEndPos > nEnd)) {
1037: // TODO messageBeep( MB_ICONASTERISK );
1038: return;
1039: } else {
1040: Transferable txfer = Toolkit.getDefaultToolkit()
1041: .getSystemClipboard().getContents(null);
1042: if (txfer
1043: .isDataFlavorSupported(DataFlavor.stringFlavor)) {
1044: try {
1045: String strPaste = (String) txfer
1046: .getTransferData(DataFlavor.stringFlavor);
1047: replaceText(field, nStartPos, nEndPos,
1048: strPaste, true);
1049: } catch (UnsupportedFlavorException e1) {
1050: e1.printStackTrace();
1051: } catch (IOException e1) {
1052: e1.printStackTrace();
1053: }
1054: }
1055: }
1056: }
1057: }
1058:
1059: /* (non-Javadoc)
1060: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#copyToClipboard()
1061: */
1062: public void copyToClipboard() {
1063: // TODO Auto-generated method stub
1064: }
1065:
1066: /**
1067: * Retrieves the text for the edit control's tooltip. The text is retrieved
1068: * in 3 parts: a left, middle (subject) and right part. The subject
1069: * part is highlighted within the tooltip and reflects the tip for the current text field.
1070: *
1071: * @param sLeft[out] The left part of the tooltip text
1072: * @param sSubject[out] The subject part of the tooltip text
1073: * @param sRight[out] The right part of the tooltip text
1074: *
1075: * @return HRESULT
1076: */
1077: public String getTooltipText() {
1078: IEditControlField pCurrField = getCurrentField();
1079: String bstrLeft = "";
1080: String bstrSubject = "";
1081: String bstrRight = "";
1082:
1083: boolean bLeft = true;
1084: boolean firstField = true;
1085: IEditControlField pField = null;
1086: while ((pField = getNextField(pField)) != null) {
1087: String sName = pField.getName();
1088: String sLead = pField.getLeadSeparator();
1089: String sTrail = pField.getTrailSeparator();
1090: String sText = pField.getToolTipText();
1091:
1092: ITranslator pTranslator = pField.getTranslator();
1093: int nStart = pField.getFieldStartPos();
1094: int nEnd = pField.getFieldEndPos();
1095: //nEnd = pField.getFieldPos(nStart);
1096:
1097: // here we check for m_nCurrentPos to be greater than the start of field
1098: // this is b/c the preceeding field's end = this field's start and they will
1099: // fight over which should be selected. So preference goes to the preceeding
1100: // field
1101: if (pTranslator != null && nStart <= getCurrentPosition()
1102: && nEnd >= getCurrentPosition()) {
1103: pTranslator.getTooltipText();
1104: String bstrLeft1 = pTranslator.getTooltipLeftText();
1105: String bstrSubject1 = pTranslator
1106: .getTooltipSubjectText();
1107: String bstrRight1 = pTranslator.getTooltipRightText();
1108:
1109: if (bLeft) {
1110: ETPairT<String, Boolean> retObj = getDelimitor(firstField);
1111: bstrLeft += retObj.getParamOne();
1112: firstField = retObj.getParamTwo().booleanValue();
1113: if (sLead != null) {
1114: bstrLeft += sLead;
1115: }
1116: bstrLeft += bstrLeft1;
1117: bstrSubject = bstrSubject1;
1118: bstrRight += bstrRight1;
1119: if (sTrail != null) {
1120: bstrRight += sTrail;
1121: }
1122: if (bstrSubject1 != null
1123: && bstrSubject1.length() > 0) {
1124: bLeft = false;
1125: }
1126: } else {
1127: ETPairT<String, Boolean> retObj = getDelimitor(firstField);
1128: bstrRight += retObj.getParamOne();
1129: firstField = retObj.getParamTwo().booleanValue();
1130: if (sLead != null) {
1131: bstrRight += sLead;
1132: }
1133: bstrRight += bstrLeft1;
1134: bstrRight += bstrSubject1;
1135: bstrRight += bstrRight1;
1136: if (sTrail != null) {
1137: bstrRight += sTrail;
1138: }
1139: }
1140: } else {
1141: if (pField.equals(pCurrField)) {
1142: ETPairT<String, Boolean> retObj = getDelimitor(firstField);
1143: bstrLeft += retObj.getParamOne();
1144: firstField = retObj.getParamTwo().booleanValue();
1145: bstrSubject = sText;
1146: bLeft = false;
1147: } else if (bLeft) {
1148: ETPairT<String, Boolean> retObj = getDelimitor(firstField);
1149: bstrLeft += retObj.getParamOne();
1150: firstField = retObj.getParamTwo().booleanValue();
1151: bstrLeft += sText;
1152: } else if (!bLeft) {
1153: ETPairT<String, Boolean> retObj = getDelimitor(firstField);
1154: bstrRight += retObj.getParamOne();
1155: firstField = retObj.getParamTwo().booleanValue();
1156: bstrRight += sText;
1157: }
1158: }
1159: }
1160: m_TooltipLeftText = bstrLeft;
1161: m_TooltipSubjectText = bstrSubject;
1162: m_TooltipRightText = bstrRight;
1163:
1164: return bstrLeft + bstrSubject + bstrRight;
1165: }
1166:
1167: /**
1168: *
1169: * Updates the edit tool tip text. Text is retrieved from each text field's TooltipText property
1170: * and concatenated together. The currently active field is highlighted.
1171: *
1172: * @return HRESULT
1173: *
1174: */
1175: public void updateToolTip() {
1176: if (m_EditControl != null) {
1177: String tooltip = getTooltipText();
1178: m_EditControl.setTooltipText(m_TooltipLeftText,
1179: m_TooltipSubjectText, m_TooltipRightText);
1180: }
1181: }
1182:
1183: /**
1184: * Retrieves the property elements that represent the elements data.
1185: * the property elements structure will be dictated by the specified
1186: * property elements.
1187: *
1188: * @param pElement [in] The element that is being processed.
1189: * @param pVal [out] The propety element.
1190: */
1191: private IPropertyElement getPropertyElement(IElement pElement) {
1192: IPropertyElement retEle = null;
1193:
1194: m_DefinitionFactory = new PropertyDefinitionFactory();
1195: m_ElementManager = new PropertyElementManager();
1196: ICoreProduct prod = ProductRetriever.retrieveProduct();
1197: if (prod != null) {
1198: IConfigManager conMan = prod.getConfigManager();
1199: if (conMan != null) {
1200: String loc = conMan.getDefaultConfigLocation();
1201: loc += "JavaLanguage.etc";
1202: m_DefinitionFactory.setDefinitionFile(loc);
1203: }
1204: }
1205: m_DefinitionFactory.buildDefinitionsUsingFile();
1206: m_ElementManager.setPDFactory(m_DefinitionFactory);
1207: m_ElementManager.setModelElement(pElement);
1208: m_ElementManager.setCreateSubs(true);
1209:
1210: IPropertyDefinition pDef = m_DefinitionFactory
1211: .getPropertyDefinitionForElement("", pElement);
1212: if (pDef != null) {
1213: if ((pDef.getID() != null) && (pDef.getID().length() > 0)) {
1214: try {
1215: Class clazz = Class.forName(pDef.getID());
1216: Class[] params = null;//{com.embarcadero.com.Dispatch.class};
1217: Constructor constructor = clazz
1218: .getConstructor(params);
1219:
1220: Object[] paramInstances = { pElement };
1221: pElement = (IElement) constructor
1222: .newInstance(paramInstances);
1223: } catch (Exception e) {
1224: }
1225: }
1226: retEle = m_ElementManager.buildTopPropertyElement(pDef);
1227: // if (retEle != null)
1228: // {
1229: // retEle = m_ElementManager.buildElement(pElement, pDef, null);
1230: // }
1231: }
1232:
1233: return retEle;
1234: }
1235:
1236: /*
1237: * Puts text fields in order, sets starting and ending positions.
1238: *
1239: */
1240: public void initTextFields() {
1241: removeFields();
1242: if (m_Element != null) {
1243: // only want to be cocreating this guy once
1244: IDataFormatter pFormatter = ProductHelper
1245: .getDataFormatter();
1246: if (pFormatter != null) {
1247: // call data formatter to get the proper property element for our model element
1248: m_PropertyElement = pFormatter
1249: .getPropertyElement(m_Element);
1250: if (m_PropertyElement != null) {
1251: // now iterate through each sub element, these will contain our individual field data
1252: Vector subEles = m_PropertyElement.getSubElements();
1253: if (subEles != null) {
1254: int count = subEles.size();
1255: for (int i = 0; i < count; i++) {
1256: IPropertyElement pEle = (IPropertyElement) subEles
1257: .elementAt(i);
1258: addField(pEle, false);
1259: }
1260: }
1261: } else {
1262: addField("No Property Element!", "");
1263: }
1264: }
1265: }
1266:
1267: // put the text fields in order
1268: updateFieldPositions(null);
1269: registerAccelerators();
1270:
1271: }
1272:
1273: /*
1274: * Replaces text in a field, updates the edit control and current position
1275: * if nStartPos or nEndPos are empty replaces from the beginning/end of the field
1276: * if sText is empty, deletes the text between nStartPos and nEndPos.
1277: *
1278: * @param pField[in]
1279: * @param nStartPos
1280: * @param nEndPos
1281: * @param sText
1282: * @param pUpdate
1283: */
1284: private boolean replaceText(IEditControlField pField,
1285: int nStartPos, int nEndPos, String sText, boolean bUpdate) {
1286: boolean retVal = true;
1287: if (pField == null) {
1288: return retVal;
1289: }
1290:
1291: // get field's current text and position
1292: String fieldText = pField.getText();
1293: int startPos = pField.getTextStartPos();
1294: int endPos = pField.getTextEndPos();
1295: //endPos = pField.getTextPos(startPos);
1296:
1297: // set defaults
1298: if (nStartPos == -1 || nStartPos < startPos
1299: || nStartPos > endPos) {
1300: nStartPos = startPos;
1301: }
1302: if (nEndPos == -1 || nEndPos > endPos || nEndPos < startPos) {
1303: nEndPos = endPos;
1304: }
1305:
1306: // calc offsets within string to insert/replace
1307: int n1 = nStartPos - startPos;
1308: int n2 = nEndPos - nStartPos;
1309:
1310: // ITranslator trans = pField.getTranslator();
1311: // if (trans == null)
1312: // {
1313: // //I want to set the proper text only if the translator is
1314: // //null, else the fieldText would be correctly calculated.
1315: // if (fieldText != null && fieldText.length() == 0)
1316: // {
1317: // fieldText = sText;
1318: // }
1319: // else
1320: // {
1321: // String leftText = "";
1322: // String rightText = "";
1323: // int nStart = pField.getTextStartPos();
1324: // //we might be adding value for a new field in which case
1325: // //initText will be "".
1326: // if (nStartPos > startPos && fieldText.length() >= (nStartPos - startPos))
1327: // {
1328: // leftText = fieldText.substring(0, nStartPos - startPos);
1329: // if (n2 > 0)
1330: // {
1331: // rightText = fieldText.substring(n1+n2);
1332: // }
1333: // else if (n1 == 0)
1334: // {
1335: // //we are adding text to the beginning
1336: // rightText = fieldText;
1337: // }
1338: // else if (sText.length() > 0)
1339: // {
1340: // //we are inserting a character
1341: // rightText = fieldText.substring(nStartPos-startPos);
1342: // }
1343: // }
1344: // else if (nStartPos == startPos)
1345: // {
1346: // if (n2 > 0)
1347: // {
1348: // rightText = fieldText.substring(n1+n2);
1349: // }
1350: // else if (n1 == 0)
1351: // {
1352: // //we are adding text to the beginning
1353: // rightText = fieldText;
1354: // }
1355: // //we are adding somthing to the start of this field
1356: // //rightText = fieldText;
1357: // }
1358: // fieldText = leftText + sText + rightText;
1359: // }
1360: // }
1361:
1362: if (n2 > 0) {
1363: //we are replacing some part
1364: //String strToReplace = fieldText.substring(n1, n2);
1365: fieldText = fieldText.substring(0, n1) + sText
1366: + fieldText.substring(n1 + n2);
1367: } else {
1368: //we are just inserting
1369: fieldText = fieldText.substring(0, n1) + sText
1370: + fieldText.substring(n1 + n2);
1371: }
1372: setCurrentPosition(nStartPos + sText.length());
1373:
1374: // by updating the text we assume we want this field visible
1375: pField.setVisible(true);
1376:
1377: pField.setText(fieldText);
1378:
1379: // inform parent something's been changed
1380: setModified(true);
1381:
1382: // update edit control
1383: if (bUpdate) {
1384: refreshEditControl();
1385: }
1386: setPosition(nStartPos + sText.length(), nStartPos
1387: + sText.length());
1388: m_Modified = true;
1389:
1390: return retVal;
1391: }
1392:
1393: /*
1394: * Toggles a field on or off, does not refresh the edit control.
1395: *
1396: * @param pField[in]
1397: * @param bVisible
1398: */
1399: private void setFieldVisible(IEditControlField pField,
1400: boolean bVisible) {
1401: if (pField == null) {
1402: return;
1403: }
1404:
1405: // determine the current state
1406: boolean visible = pField.getVisible();
1407:
1408: // if anything to do change the field's state and reposition trailing fields
1409: if (visible != bVisible) {
1410: pField.setVisible(bVisible);
1411:
1412: // move trailing fields
1413: updateFieldPositions(null);
1414: }
1415: }
1416:
1417: /**
1418: * Updates the edit control with the contents of the fields.
1419: */
1420: private void refreshEditControl() {
1421: if (m_EditControl != null) {
1422: m_EditControl.refresh();
1423: m_EditControl.setSel(getCurrentPosition(),
1424: getCurrentPosition());
1425: updateHints();
1426: }
1427: }
1428:
1429: /**
1430: * Selects the entire field in the edit control.
1431: *
1432: * @param pField[in]
1433: */
1434: private void selectField(IEditControlField pField) {
1435: if (pField == null) {
1436: return;
1437: }
1438:
1439: ITranslator translator = pField.getTranslator();
1440: if (translator != null) {
1441: // defer to contained translator, since we don't know what to select have it
1442: // behave as if it has been first selected.
1443: translator.onSetFocus();
1444: } else {
1445: // KSL this used to test if visible however we now allow the caret to be placed at the beginning of the
1446: // default field, which could be hidden at present.
1447: int startPos = pField.getTextStartPos();
1448: int endPos = pField.getTextEndPos();
1449: //endPos = pField.getTextPos(startPos);
1450: setSel(startPos, endPos);
1451: setCurrentPosition(startPos);
1452: }
1453: updateHints();
1454: }
1455:
1456: private IEditControlField addField(IEditControlField pField) {
1457: Vector pFields = getTextFields();
1458: if (pField != null) {
1459: pFields.add(pField);
1460: }
1461: return pField;
1462: }
1463:
1464: public IEditControlField addFieldDefinition(
1465: IPropertyDefinition pDef, IEditControlField pInsField) {
1466: IEditControlField retField = null;
1467: Vector pFields = getTextFields();
1468: if (pFields != null) {
1469: IEditControlField pField = new EditControlField();
1470: pField.setOwnerTranslator(this );
1471: pField.setPropertyDefinition(pDef);
1472: IEditControl editCtrl = getEditControl();
1473:
1474: ITranslator translator = pField.getTranslator();
1475: if (translator != null) {
1476: translator.setEditControl2(editCtrl);
1477: }
1478:
1479: if (pInsField == null) {
1480: // insert at the end
1481: pFields.add(pField);
1482: } else {
1483: // find our insertion point
1484: int pos = 0;
1485: for (int i = 0; i < pFields.size(); i++) {
1486: IEditControlField field = (IEditControlField) pFields
1487: .elementAt(i);
1488: if (field.equals(pInsField)) {
1489: break;
1490: }
1491: pos++;
1492: }
1493: pFields.insertElementAt(pField, pos);
1494: }
1495:
1496: retField = pField;
1497:
1498: // add our separators and delimitors to the edit control's master list
1499: if (m_EditControl != null && pField != null) {
1500: String sTemp = m_EditControl.getSeparatorList();
1501: String separators = sTemp;
1502:
1503: String str = pField.getLeadSeparator();
1504: separators = updateSeparatorList(separators, str);
1505:
1506: str = pField.getTrailSeparator();
1507: separators = updateSeparatorList(separators, str);
1508:
1509: str = pField.getDelimitor();
1510: separators = updateSeparatorList(separators, str);
1511:
1512: sTemp = separators;
1513: m_EditControl.setSeparatorList(sTemp);
1514: }
1515: }
1516: return retField;
1517: }
1518:
1519: private void removeFields() {
1520: if (m_TextFields != null) {
1521: m_TextFields.removeAllElements();
1522: }
1523: }
1524:
1525: /**
1526: * Returns the minimum bounding rect around the text given the current font.
1527: *
1528: * @param hDC[in]
1529: * @param size[out]
1530: */
1531: private Dimension getTextExtent() {
1532: Dimension retObj = new Dimension();
1533: Dimension minSize = new Dimension();
1534: minSize.height = 0;
1535: minSize.width = 0;
1536: int count = m_TextFields.size();
1537: for (int i = 0; i < count; i++) {
1538: IEditControlField pField = (IEditControlField) m_TextFields
1539: .elementAt(i);
1540: Dimension sz = getTextExtent(pField);
1541: if (sz.height > minSize.height) {
1542: minSize.height = sz.height;
1543: }
1544: if (sz.width > minSize.width) {
1545: minSize.width = sz.width;
1546: }
1547: }
1548: retObj.height = minSize.height;
1549: retObj.width = minSize.width;
1550: return retObj;
1551: }
1552:
1553: /**
1554: * Internal helper for get_TextExtent.
1555: *
1556: * @param pField[in]
1557: */
1558: private Dimension getTextExtent(IEditControlField pField) {
1559: Dimension retObj = new Dimension();
1560: if (pField != null) {
1561: String text = pField.getText();
1562: Font font = pField.getFont();
1563:
1564: //now use this font and text to determine how much should be the width and height.
1565: }
1566: return retObj;
1567: }
1568:
1569: /*
1570: * adds the field for this property element
1571: */
1572: public void addField(IPropertyElement pData, boolean bNoUpdate) {
1573: IEditControlField pField = null;
1574: IPropertyDefinition pDef = null;
1575: if (pData != null) {
1576: pDef = pData.getPropertyDefinition();
1577: }
1578:
1579: if (pDef != null) {
1580: String name = pDef.getName();
1581: boolean found = false;
1582:
1583: // look for an existing property definition
1584: IEditControlField pTempField = getNextField(null);
1585: while (pTempField != null) {
1586: IPropertyElement pTempEle = pTempField
1587: .getPropertyElement();
1588: IPropertyDefinition pTempDef = pTempField
1589: .getPropertyDefinition();
1590: if (pTempDef != null && pTempDef.equals(pDef)) {
1591: if (pTempEle == null) {
1592: // found an existing, empty field using our definition.
1593: IDataFormatter pFormatter = ProductHelper
1594: .getDataFormatter();
1595: if (pFormatter != null) {
1596: //pFormatter.processEnumeration(pData);
1597: }
1598:
1599: // Attach ourselves to this field
1600: if (bNoUpdate) {
1601: pTempField.setPropertyElement2(pData);
1602: } else {
1603: pTempField.setPropertyElement(pData);
1604: }
1605: found = true;
1606: break;
1607: }
1608: }
1609: pTempField = getNextField(pTempField);
1610: }
1611:
1612: // if no empty fields using this definition, create and append a new field
1613: if (!found) {
1614: // create new textfield, add to end of the list
1615: pField = new EditControlField();
1616:
1617: // provide the field with a back pointer to this translator
1618: pField.setOwnerTranslator(this );
1619:
1620: // if the raw data contains enumerated values, convert them here
1621: IDataFormatter pFormatter = ProductHelper
1622: .getDataFormatter();
1623: if (pFormatter != null) {
1624: //pFormatter.processEnumeration(pData);
1625: }
1626:
1627: // add the field to our array
1628: addField(pField);
1629:
1630: // save the data into the field, this reads the formatting information into the field
1631: pField.setPropertyElement(pData);
1632:
1633: // now, if the field contains sub-fields, set their edit control (I don't think this should be necessary)
1634: ITranslator pTrans = pField.getTranslator();
1635: if (pTrans != null) {
1636: IEditControl pCtrl = getEditControl();
1637: pTrans.setEditControl2(pCtrl);
1638: }
1639: }
1640:
1641: // add our separators and delimitors to the edit control's master list
1642: if (m_EditControl != null && pField != null) {
1643: String sTemp = m_EditControl.getSeparatorList();
1644: String separators = sTemp;
1645:
1646: sTemp = pField.getLeadSeparator();
1647: separators = updateSeparatorList(separators, sTemp);
1648:
1649: sTemp = pField.getTrailSeparator();
1650: separators = updateSeparatorList(separators, sTemp);
1651:
1652: sTemp = pField.getDelimitor();
1653: separators = updateSeparatorList(separators, sTemp);
1654:
1655: sTemp = separators;
1656: m_EditControl.setSeparatorList(sTemp);
1657: }
1658: }
1659: }
1660:
1661: private String updateSeparatorList(String separators, String str) {
1662: String retVal = separators;
1663: if (separators != null && str != null) {
1664: int length = str.length();
1665: for (int i = 0; i < length; i++) {
1666: char c = str.charAt(i);
1667: int pos = separators.indexOf(c);
1668: if (pos < 0) {
1669: separators += c;
1670: }
1671: }
1672: retVal = separators;
1673: }
1674: return retVal;
1675: }
1676:
1677: private IEditControlField addField(String text, String tooltipText) {
1678: IEditControlField pField = null;
1679: Vector fields = getTextFields();
1680: if (fields != null) {
1681: pField = new EditControlField();
1682: pField.init(text, null, null);
1683: if (tooltipText != null && tooltipText.length() > 0) {
1684: pField.setToolTipText(tooltipText);
1685: }
1686: fields.add(pField);
1687: }
1688: return pField;
1689: }
1690:
1691: /**
1692: * Sets the edit control's tooltip and hint bar
1693: */
1694: public void updateHints() {
1695: if (m_EditControl != null) {
1696: m_EditControl.hideHintBar();
1697: IEditControlField pField = getCurrentField();
1698: if (pField != null) {
1699: int kind = pField.getEditKind();
1700:
1701: if (kind == ITextFieldEditKind.TFEK_LIST
1702: || kind == ITextFieldEditKind.TFEK_COMBO) {
1703: int nStart = pField.getTextStartPos();
1704: int nEnd = pField.getTextEndPos();
1705: //nEnd = pField.getTextPos(nStart);
1706: m_EditControl.showHintBar(nStart);
1707: }
1708: }
1709: m_EditControl.updateToolTip();
1710: }
1711: }
1712:
1713: /**
1714: * Sets the edit control's tooltip and hint bar
1715: */
1716: public void handleHint() {
1717: if (m_EditControl != null) {
1718: IEditControlField pField = getCurrentField();
1719: if (pField != null) {
1720: ITranslator pTrans = pField.getTranslator();
1721: if (pTrans != null) {
1722: pTrans.handleHint();
1723: } else {
1724: IPropertyElement pEle = pField.getPropertyElement();
1725: IPropertyDefinition pDef = pField
1726: .getPropertyDefinition();
1727: IStrings list = null;
1728:
1729: if (pDef != null && pEle != null) {
1730: // if we have this information, use it to determine the picklist
1731: // we will have this if the item that we are editing has a model element
1732: // associated with it
1733: list = pDef.getValidValue(pEle);
1734: } else {
1735: // we do not have a property element, so this is a new element (insert attribute
1736: // for example)
1737: // in order to get the picklist manager, we need the project, since we have no
1738: // model element, we have no way of getting the project
1739: IProduct prod = ProductHelper.getProduct();
1740: if (prod != null) {
1741: IProductProjectManager pMan = prod
1742: .getProjectManager();
1743: if (pMan != null) {
1744: IProject proj = pMan
1745: .getCurrentProject();
1746: if (proj != null) {
1747: ITypeManager typeMan = proj
1748: .getTypeManager();
1749: if (typeMan != null) {
1750: IPickListManager pickMan = typeMan
1751: .getPickListManager();
1752: if (pickMan != null) {
1753: String filter = "DataType Class Interface";
1754: list = pickMan
1755: .getTypeNamesWithStringFilter(filter);
1756:
1757: filter = "ParameterableElement";
1758: Object mElem = null;
1759: IEditControlField field = getCurrentField();
1760: while (mElem == null
1761: && field != null) {
1762: IPropertyElement pe = field
1763: .getPropertyElement();
1764: if (pe != null) {
1765: mElem = pe
1766: .getElement();
1767: }
1768: if (mElem == null) {
1769: ITranslator translator = field
1770: .getOwnerTranslator();
1771: if (translator != null) {
1772: field = translator
1773: .getParentField();
1774: } else {
1775: break;
1776: }
1777: }
1778: }
1779:
1780: INamespace space = null;
1781: if (mElem instanceof INamespace) {
1782: space = (INamespace) mElem;
1783: } else if (mElem instanceof INamedElement) {
1784: space = ((INamedElement) mElem)
1785: .getNamespace();
1786: }
1787: list
1788: .append(pickMan
1789: .getTypeNamesWithStringFilterNamespaceVisible(
1790: filter,
1791: false,
1792: space));
1793: }
1794: }
1795: }
1796: }
1797: }
1798: }
1799: if (list != null) {
1800: list = ensureSorted(list);
1801: long count = list.getCount();
1802: if (count > 0) {
1803: // right now we assume we're dealing with a list
1804: int nStart = pField.getTextStartPos();
1805: int nEnd = pField.getTextEndPos();
1806: //nEnd = pField.getTextPos(nStart);
1807: selectField(pField);
1808:
1809: // fetch seed value from our text
1810: String text = pField.getText();
1811:
1812: // launch the listbox
1813: m_EditControl.displayList(true, list,
1814: nStart, text);
1815: }
1816: }
1817: }
1818: }
1819: }
1820: }
1821:
1822: private IStrings ensureSorted(IStrings list) {
1823: if (list != null) {
1824: Object[] objs = list.toArray();
1825: if (objs != null) {
1826: Arrays.sort(objs);
1827: list.clear();
1828: for (int i = 0; i < objs.length; i++) {
1829: list.add((String) objs[i]);
1830: }
1831: }
1832: }
1833: return list;
1834: }
1835:
1836: /**
1837: * Copies the changed data back into our property elements
1838: *
1839: */
1840: public void saveFields() {
1841: if (m_TextFields != null) {
1842: int count = m_TextFields.size();
1843: if (count > 0) {
1844: if (m_Element instanceof IOperation) {
1845: IOperation oper = (IOperation) m_Element;
1846:
1847: // We need to put the dispatch controller into a
1848: // batch mode, specifically an IOperationSignatureChangeContext
1849: // mode in order to not process the individual events coming
1850: // resulting from the various field saves
1851:
1852: IOperationSignatureChangeContextManager pSigChange = new OperationSignatureChangeContextManager();
1853: try {
1854: pSigChange.startSignatureChange(oper);
1855: saveFields(count);
1856: } finally {
1857: pSigChange.endSignatureChange();
1858: }
1859: } else {
1860: saveFields(count);
1861: }
1862: }
1863: }
1864: }
1865:
1866: /**
1867: *
1868: * Saves all the fields in the m_Fields collection
1869: *
1870: * @param numFields[in] The number of fields in m_Fields
1871: *
1872: * @return HRESULT
1873: *
1874: */
1875: private void saveFields(int numFields) {
1876: boolean bCancel = false;
1877: for (int i = 0; i < numFields; i++) {
1878: IEditControlField pField = (IEditControlField) m_TextFields
1879: .elementAt(i);
1880:
1881: // cancel flag gets set if this node gets deleted during the save
1882: bCancel = pField.save();
1883: if (bCancel) {
1884: break;
1885: }
1886: }
1887: }
1888:
1889: public boolean canNavigateSeparator(int nChar) {
1890: IEditControlField pField = getCurrentField();
1891:
1892: boolean isInert = false;
1893: if (pField != null) {
1894: isInert = pField.checkInertSeparator(nChar, getPosition());
1895: }
1896:
1897: return (isInert == false);
1898: }
1899:
1900: /**
1901: * Get the value of a text field contained by this translat
1902: * (cannot be used for separator fields).
1903: *
1904: * @param nKind[in]
1905: * @param sText[out]
1906: */
1907: private String getFieldText(IEditControlField pField) {
1908: String retText = "";
1909: boolean visible = false;
1910: if (pField != null) {
1911: visible = pField.getVisible();
1912: if (visible) {
1913: retText = pField.getText();
1914: }
1915: }
1916: return retText;
1917: }
1918:
1919: /**
1920: *
1921: * Return the selection range of the edit control. If no text is selected
1922: * both return values will indicate the current cursor position.
1923: *
1924: * @param nStartPos[out] The first selected character position.
1925: * @param nEndPos[out] The last selected character position.
1926: *
1927: * @return
1928: *
1929: */
1930: private void getSel(int nStartPos, int nEndPos) {
1931: if (m_EditControl != null) {
1932: m_EditControl.getSel(nStartPos, nEndPos);
1933: } else {
1934: // can't simulate selection if no edit control
1935: nStartPos = getCurrentPosition();
1936: nEndPos = getCurrentPosition();
1937: }
1938: }
1939:
1940: /**
1941: *
1942: * Selects a range of text in the edit control.
1943: *
1944: * @param nStartPos[in] The first selected character position
1945: * @param nEndPos[in] The last selected character position
1946: *
1947: * @return
1948: *
1949: */
1950: public void setSel(int nStartPos, int nEndPos) {
1951: try {
1952: if (m_EditControl != null) {
1953: m_EditControl.setSel(nStartPos, nEndPos);
1954: }
1955: } catch (Exception e) {
1956: }
1957: }
1958:
1959: /**
1960: *
1961: * Returns the length of the text in the edit control.
1962: *
1963: * @param nLength[out] The string length
1964: * @param bOverallLength[in] For multi-line edit controls, the function can
1965: * return the overall length of all text in the control (true), or just the
1966: * length of the current line (false)
1967: *
1968: * @return
1969: *
1970: */
1971: private int getLineLength(boolean bOverallLength) {
1972: int length = 0;
1973: if (m_EditControl != null) {
1974: int index = 0;
1975: if (bOverallLength) {
1976: index = m_EditControl.lineIndex(-1);
1977: }
1978: length = m_EditControl.lineLength(-1);
1979: length += index;
1980: } else {
1981: // no edit control, return length of all visible fields
1982: IEditControlField pField = getNextVisibleField(null);
1983: while (pField != null) {
1984: String str = pField.getText();
1985: length += str.length();
1986: pField = getNextVisibleField(pField);
1987: }
1988: }
1989: return length;
1990: }
1991:
1992: /* (non-Javadoc)
1993: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#onMouseMove(int, int)
1994: */
1995: public void onMouseMove(int x, int y) {
1996: // TODO Auto-generated method stub
1997: }
1998:
1999: /**
2000: * Updates text in response to the hint list being closed
2001: */
2002: public IEditControlField handleHintText(String sText) {
2003: IEditControlField pField = getCurrentField();
2004: if (pField != null) {
2005: ITranslator pTrans = pField.getTranslator();
2006: if (pTrans != null) {
2007: pField = pTrans.handleHintText(sText);
2008: } else {
2009: pField.setText(sText);
2010:
2011: int nStart = pField.getTextStartPos();
2012: int nEnd = pField.getTextEndPos();
2013: //nEnd = pField.getTextPos(nStart);
2014: setCurrentPosition(nEnd);
2015: refreshEditControl();
2016: }
2017: }
2018:
2019: return pField;
2020: }
2021:
2022: /**
2023: * Does one of this translator's text fields have a separator for this character? If so
2024: * perform the appropriate action. The default is to select the field, or insert a new
2025: * one if entering a comma for repeating fields.
2026: *
2027: * @param[in] nChar The keycode passed during WM_KEYDOWN message processing.
2028: * @param[in] nCurrentPos The current caret position.
2029: * @param[out,retval] bHandled Returns TRUE if this character is a separator for one of the
2030: * textfields contained by this translator.
2031: * @param[out,retval] bHandled Returns TRUE if this character is a separator for one of the
2032: * textfields contained by this translator.
2033: *
2034: * @return HRESULT
2035: */
2036: public ETPairT<Boolean, Boolean> handleSeparator(int nChar,
2037: int nCurrentPos) {
2038: boolean isHandled = false;
2039: boolean bSelectNextField = false;
2040: setCurrentPosition(nCurrentPos);
2041:
2042: // //////////////////////////////////////////////////////
2043: //
2044: // All cases:
2045: // 1) Translators typically contain 1 or more textfields. Shortcut characters are special characters
2046: // that the user types to quickly navigate to a field. The character is always a non-space, non-text
2047: // (symbolic) such as ":" or "=".
2048: //
2049: // 2) Always begin searching for the shortcut by looking in all fields TO THE RIGHT of the current
2050: // caret position. Search visible and hidden fields as the user may be wishing to activate a
2051: // hidden field. If not found resume the search from the beginning of text.
2052: //
2053: // If a text field is found for the shortcut, move the caret and select the text. If the field is
2054: // hidden or empty, place the caret where the text should begin.
2055: //
2056: // Specific cases
2057: // 3) This translator contains normal text fields, in which case the accelerator is one of the
2058: // non-text, non-space characters in either the leading or the trailing separator of one of
2059: // the fields. Search the field list as described in para 2), if found select the field.
2060: //
2061: // 4) This translator contains a single text field that contains another translator (nested fields).
2062: // First look for this field's shortcut in its leading and trailing separator, if found select
2063: // the first text field contained by the nested translator.
2064: //
2065: // If this field does not have a shortcut pass the search to the nested translator to let it search.
2066: // If it finds a shortcut it handles it appropriately. If not found it returns FALSE, and we continue
2067: // searching our remaining fields as described in paragraph 2.
2068: //
2069: // 5) If the translator contains repeating fields (multiplicity = 0 or multiplicity > 1) and no shortcut was found
2070: // of the existing fields, check for the delimitor character. If found the user is attempting to
2071: // navigate among the repeating fields, or insert a new field. First test for succeeding fields
2072: // past the current caret position (the current field). If found they will be separated by the
2073: // delimitor character. Treat this as a regular shortcut, that is move the caret to the first
2074: // text field in the repeating field and select it. If no more fields follow the current field or the
2075: // current field is empty/hidden, create a new repeating field. If fields already exist place
2076: // the new field after the last field in the list, separated by the delimiter character, otherwise
2077: // the new field becomes the first field in the list.
2078: //
2079: // 6) Consider Ctrl+delimitor to mean to insert a new repeating field at the current caret position.
2080: //
2081: // ///////////////////////////////////////////////////////
2082:
2083: IEditControlField pField = getCurrentField();
2084: boolean isDuplicate = isDuplicateSeperator(pField, nChar,
2085: nCurrentPos);
2086: if (isDuplicate) {
2087: isHandled = true;
2088: return new ETPairT<Boolean, Boolean>(Boolean
2089: .valueOf(isHandled), Boolean
2090: .valueOf(bSelectNextField));
2091: }
2092:
2093: // first thing we do is check the current field
2094: if (pField != null) {
2095: // this could return false if the current position is within the
2096: // current field (check goes from current pos to the right)
2097: ETPairT<Boolean, Boolean> retObj = handleSeparator(pField,
2098: nChar, nCurrentPos);
2099: isHandled = ((Boolean) retObj.getParamOne()).booleanValue();
2100: bSelectNextField = ((Boolean) retObj.getParamTwo())
2101: .booleanValue();
2102: }
2103:
2104: // no current field or current field did not handle the separator
2105: if (!isHandled) {
2106: pField = getNextField(pField);
2107:
2108: // current field didnt' handle it, now we check successive fields
2109: while (pField != null) {
2110: ETPairT<Boolean, Boolean> retObj = handleSeparator(
2111: pField, nChar, nCurrentPos);
2112: isHandled = ((Boolean) retObj.getParamOne())
2113: .booleanValue();
2114: bSelectNextField = ((Boolean) retObj.getParamTwo())
2115: .booleanValue();
2116:
2117: if (isHandled) {
2118: break;
2119: }
2120: pField = getNextField(pField);
2121: }
2122: }
2123:
2124: if (isHandled) {
2125: if (bSelectNextField) {
2126: boolean visible = pField.getVisible();
2127: if (visible) {
2128: // found trailing separator, select following field
2129: pField = getNextVisibleField(pField);
2130: if (pField == null) {
2131: // no more fields, ask our parent to select it for us
2132: bSelectNextField = true;
2133: } else {
2134: selectField(pField);
2135: }
2136: }
2137: }
2138: }
2139: return new ETPairT<Boolean, Boolean>(
2140: Boolean.valueOf(isHandled), Boolean
2141: .valueOf(bSelectNextField));
2142: }
2143:
2144: /**
2145: * Helper to test a field for separators
2146: *
2147: * @param[in] <Name Description>
2148: *
2149: * @return HRESULT
2150: */
2151: private ETPairT<Boolean, Boolean> handleSeparator(
2152: IEditControlField pField, int nChar, int nCurrentPos) {
2153: boolean isHandled = false;
2154: boolean bSelectNextField = false;
2155: if (pField != null) {
2156: boolean visible = pField.getVisible();
2157:
2158: if (handleLeadSeperator(pField, nChar, nCurrentPos)) {
2159: isHandled = true;
2160: } else if (visible) {
2161: ETPairT<Boolean, Boolean> retObj = handleSubFieldSeperator(
2162: pField, nChar, nCurrentPos);
2163: isHandled = ((Boolean) retObj.getParamOne())
2164: .booleanValue();
2165: bSelectNextField = ((Boolean) retObj.getParamTwo())
2166: .booleanValue();
2167: if (isHandled) {
2168: return new ETPairT<Boolean, Boolean>(Boolean
2169: .valueOf(isHandled), Boolean
2170: .valueOf(bSelectNextField));
2171: }
2172:
2173: if (handleTrailSeperator(pField, nChar)) {
2174: isHandled = true;
2175: IEditControlField pNextField = getNextVisibleField(pField);
2176:
2177: if (pNextField == null) {
2178: pNextField = getNextField(pField);
2179: }
2180:
2181: pField = pNextField;
2182: if (pField == null) {
2183: // no more fields, ask our parent to select it for us
2184: bSelectNextField = true;
2185: } else {
2186: selectField(pField);
2187: }
2188: }
2189: }
2190:
2191: if (isHandled && pField != null) {
2192: // we have a separator, make the field visible and selected
2193: // we only need to do the current field
2194: if (m_EditControl != null) {
2195: IEditControlField pCurrentField = m_EditControl
2196: .getCurrentField();
2197: if (pCurrentField != null
2198: && !pCurrentField.equals(pField)) {
2199: updateVisibleFields(pCurrentField);
2200: }
2201: }
2202: pField.setVisible(true);
2203: refreshEditControl();
2204: selectField(pField);
2205: }
2206: }
2207: return new ETPairT<Boolean, Boolean>(
2208: Boolean.valueOf(isHandled), Boolean
2209: .valueOf(bSelectNextField));
2210: }
2211:
2212: /**
2213: * Inserts a new field in response to the delimitor character having been entered.
2214: *
2215: * @param[in] nChar The keycode passed during WM_KEYDOWN message processing.
2216: *
2217: * @return HRESULT
2218: */
2219: public boolean handleDelimitor(int nChar, int nCurrentPos) {
2220: boolean isHandled = false;
2221: setCurrentPosition(nCurrentPos);
2222:
2223: if (isOnDelimitor(nChar)) // Jump to next field or insert one.
2224: {
2225: isHandled = true;
2226: boolean isControlDown = false; //ctrlDown();
2227: if (isControlDown) {
2228: IEditControlField pField = getCurrentField();
2229: if (pField != null) {
2230: createField(pField, true);
2231: } else {
2232: //don't allow this input.
2233: }
2234: } else {
2235: if (getPreviousVisibleField(null) != null
2236: && jumpToNextField() == null) {
2237: // this is the last field, add a new one at the end
2238: IEditControlField pField = getPreviousField(null);
2239: createField(pField, false);
2240: }
2241: }
2242: }
2243:
2244: return isHandled;
2245: }
2246:
2247: /**
2248: * Top level separator handler, this routine gets called once by the edit control for the
2249: * top level translator;
2250: *
2251: * @param[in] nChar The keycode passed during WM_KEYDOWN message processing.
2252: * @param[out,retval] bHandled Returns TRUE if this character is a separator for one of the
2253: * textfields contained by this translator.
2254: *
2255: * @return HRESULT
2256: */
2257: public boolean handleTopLevelSeparators(int nChar) {
2258: boolean isHandled = false;
2259: if (canNavigateSeparator(nChar)) {
2260: boolean bSelectNextField = false;
2261: IEditControlField pField = getCurrentField();
2262: int nCurrentPos = getCurrentPosition();
2263:
2264: // first thing we do is check the current field
2265: if (pField != null) {
2266: // this could return false if the current position is within the
2267: // current field (check goes from current pos to the right)
2268: ETPairT<Boolean, Boolean> retObj = handleSeparator(
2269: pField, nChar, nCurrentPos);
2270: isHandled = ((Boolean) retObj.getParamOne())
2271: .booleanValue();
2272: bSelectNextField = ((Boolean) retObj.getParamTwo())
2273: .booleanValue();
2274: }
2275:
2276: // no current field or current field did not handle the separator
2277: if (!isHandled) {
2278: IEditControlField pStartField = pField;
2279: pField = getNextField(pField);
2280:
2281: // current field didnt' handle it, now we check successive fields
2282: while (pField != null && !pField.equals(pStartField)
2283: && !isHandled) {
2284: ETPairT<Boolean, Boolean> retObj = handleSeparator(
2285: pField, nChar, nCurrentPos);
2286: isHandled = ((Boolean) retObj.getParamOne())
2287: .booleanValue();
2288: bSelectNextField = ((Boolean) retObj.getParamTwo())
2289: .booleanValue();
2290:
2291: if (isHandled) {
2292: break;
2293: }
2294: pField = getNextField(pField);
2295: }
2296: }
2297:
2298: if (isHandled) {
2299: if (bSelectNextField) {
2300: boolean visible = pField.getVisible();
2301: if (visible) {
2302: // found trailing separator, select following field
2303: pField = getNextVisibleField(pField);
2304: if (pField != null) {
2305: selectField(pField);
2306: }
2307: }
2308: }
2309: }
2310: }
2311: return isHandled;
2312: }
2313:
2314: /* (non-Javadoc)
2315: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#dump(java.lang.String)
2316: */
2317: public void dump(String sPad) {
2318: // TODO Auto-generated method stub
2319: }
2320:
2321: /**
2322: * Returns the field following this field, NULL if none.
2323: *
2324: * @param pPrevious The field from which to start the search. If NULL then the first field is returned;
2325: */
2326: public IEditControlField getNextField(
2327: IEditControlField pPreviousField) {
2328: IEditControlField retObj = null;
2329: if (m_TextFields != null) {
2330: int count = m_TextFields.size();
2331: boolean found = false;
2332: for (int i = 0; i < count; i++) {
2333: retObj = (IEditControlField) m_TextFields.elementAt(i);
2334: if (found || pPreviousField == null) {
2335: break;
2336: }
2337: if (retObj.equals(pPreviousField)) {
2338: found = true;
2339: }
2340: retObj = null;
2341: }
2342: }
2343: return retObj;
2344: }
2345:
2346: /**
2347: * Returns the next visible field following this field, NULL if none. The field must be both visible and enabled.
2348: *
2349: * @param pPrevious The field from which to begin the search. If NULL then the first visible field is returned.
2350: */
2351: private IEditControlField getNextVisibleField(
2352: IEditControlField pPrevious) {
2353: IEditControlField retField = null;
2354:
2355: // KSL return the next visible field OR the current field even if not visible
2356: IEditControlField pCurrentField = getCurrentField();
2357:
2358: retField = getNextField(pPrevious);
2359: while (retField != null) {
2360: boolean visible = false;
2361: visible = retField.getVisible();
2362:
2363: // KSL used to be visible AND enabled
2364: if (visible || retField.equals(pCurrentField)) {
2365: break;
2366: }
2367:
2368: retField = getNextField(retField);
2369: }
2370:
2371: return retField;
2372: }
2373:
2374: /**
2375: * Returns the next visible field preceeding this field, NULL if none.
2376: *
2377: * @param pNext[in]
2378: */
2379: private IEditControlField getPreviousVisibleField(
2380: IEditControlField pNext) {
2381: IEditControlField retField = null;
2382: retField = getPreviousField(pNext);
2383: while (retField != null) {
2384: boolean visible = retField.getVisible();
2385: if (visible) {
2386: break;
2387: }
2388: retField = getPreviousField(retField);
2389: }
2390: return retField;
2391: }
2392:
2393: /**
2394: * Returns the field preceeding this field, NULL if none. If pNext is null returns the last field.
2395: *
2396: * @param pNext[in]
2397: */
2398: public IEditControlField getPreviousField(
2399: IEditControlField pNextField) {
2400: IEditControlField pField = null;
2401: IEditControlField pTest = null;
2402:
2403: if (m_TextFields != null) {
2404: int count = m_TextFields.size();
2405: if (pNextField != null) {
2406: for (int i = 0; i < count; i++) {
2407: pTest = (IEditControlField) m_TextFields
2408: .elementAt(i);
2409: if (pTest.equals(pNextField)) {
2410: break;
2411: }
2412: pField = null;
2413: pField = pTest;
2414: pTest = null;
2415: }
2416: } else {
2417: pField = (IEditControlField) m_TextFields
2418: .elementAt(count - 1);
2419: }
2420: }
2421:
2422: return pField;
2423: }
2424:
2425: /**
2426: * Returns the default field, this is the field that gets initial editing focus.
2427: *
2428: * @param pPrevious The field from which to begin the search. If NULL then the first visible field is returned.
2429: */
2430: private IEditControlField getDefaultField() {
2431: IEditControlField retField = null;
2432: retField = getNextField(null);
2433: while (retField != null) {
2434: boolean bDefault = retField.getDefault();
2435: if (bDefault) {
2436: break;
2437: }
2438: retField = getNextField(retField);
2439: }
2440: if (retField == null) {
2441: retField = getNextField(null);
2442: }
2443:
2444: return retField;
2445: }
2446:
2447: /**
2448: * Moves a field to the new starting position within the string.
2449: */
2450: private void moveField(IEditControlField pField, int nPosition) {
2451: if (pField != null) {
2452: pField.setFieldPos(nPosition);
2453: }
2454: }
2455:
2456: /**
2457: * Returns the first field in the list, NULL if none.
2458: */
2459: private IEditControlField getFirstField() {
2460: IEditControlField retField = null;
2461: if (m_TextFields != null) {
2462: int count = m_TextFields.size();
2463: if (count > 0) {
2464: retField = (IEditControlField) m_TextFields
2465: .elementAt(0);
2466: }
2467: }
2468: return retField;
2469: }
2470:
2471: /**
2472: * Returns the last field in the list, NULL if none
2473: */
2474: private IEditControlField getLastField() {
2475: IEditControlField retField = null;
2476: if (m_TextFields != null) {
2477: int count = m_TextFields.size();
2478: if (count > 0) {
2479: retField = (IEditControlField) m_TextFields
2480: .elementAt(count - 1);
2481: }
2482: }
2483: return retField;
2484: }
2485:
2486: /**
2487: * Updates all contained text fields with the property elements provided. Does not load the
2488: * property element data into the field (existing field data is preserved).
2489: *
2490: * @param[in] pElements A collection of property elements to load. Typically textfields containing
2491: * just PropertyDefinitions already exist, these elements will be attached to their respective fields.
2492: *
2493: * @return HRESULT
2494: */
2495: public void updateFields(Vector pElements) {
2496: if (pElements != null) {
2497: int count = pElements.size();
2498: for (int i = 0; i < count; i++) {
2499: IPropertyElement subEle = (IPropertyElement) pElements
2500: .elementAt(i);
2501: addField(subEle, true);
2502: }
2503: }
2504: }
2505:
2506: /**
2507: * Helper function to returns the PropertyElement for a translator that
2508: * contains a single field (these fields usually contain nested fields)
2509: *
2510: * @param[out,retval] pElement The propertyElement. Return is NULL if the translator
2511: * does not contain 1 and only 1 textfield, or if the textfield's PropertyElement
2512: * has not been set.
2513: *
2514: * @return HRESULT
2515: */
2516: public IEditControlField getParentField() {
2517: return m_ParentField;
2518: }
2519:
2520: /**
2521: * Gets the translator that contains this this translator's owner text field. Valid only for
2522: * "nested" translators, that is translators that contain subfields.
2523: *
2524: * @param[out,retval] pTranslator The Translator that owns the textfield that owns this translator.
2525: *
2526: * @return HRESULT
2527: */
2528: public void setParentField(IEditControlField pField) {
2529: m_ParentField = pField;
2530: }
2531:
2532: /**
2533: * Shifts all fields following this one, used after resizing this field.
2534: *
2535: * @param pCurrent[in]
2536: */
2537: public void updateFieldPositions(IEditControlField pCurrent) {
2538: if (pCurrent == null) {
2539: pCurrent = getFirstField();
2540: }
2541:
2542: // if called before initializing this could be null
2543: if (pCurrent != null) {
2544: int startPos = pCurrent.getFieldStartPos();
2545: int endPos = pCurrent.getFieldEndPos();
2546:
2547: // fetch starting position
2548: //endPos = pCurrent.getFieldPos(startPos);
2549: moveField(pCurrent, startPos);
2550:
2551: // fetch new ending position
2552: endPos = pCurrent.getFieldEndPos();
2553:
2554: // find the next field
2555: IEditControlField pField = getNextField(pCurrent);
2556: while (pField != null) {
2557: moveField(pField, endPos);
2558: startPos = pField.getFieldStartPos();
2559: endPos = pField.getFieldEndPos();
2560: pField = getNextField(pField);
2561: }
2562: }
2563: }
2564:
2565: /**
2566: * Informs the field that editing has finished and it should apply whatever validation it needs to.
2567: * @param[in] pField The field to update, if NULL the current field is updated.
2568: *
2569: * @return HRESULT
2570: */
2571: public void updateField(IEditControlField pField) {
2572: if (pField == null) {
2573: pField = getCurrentField();
2574: }
2575: if (pField != null) {
2576: pField.update();
2577: }
2578: }
2579:
2580: /**
2581: * Is this translator deleted? A translator is deleted if all its contained fields are deleted.
2582: *
2583: * @param[out] bDeleted TRUE or FALSE
2584: *
2585: * @return HRESULT
2586: */
2587: public boolean getDeleted() {
2588: boolean isDeleted = false;
2589: IEditControlField pField = getNextField(null);
2590: while (pField != null) {
2591: isDeleted = pField.getDeleted();
2592: if (isDeleted) {
2593: break;
2594: }
2595: pField = getNextField(pField);
2596: }
2597: return isDeleted;
2598: }
2599:
2600: /**
2601: * Set this translator's deleted state. All contained fields are set to the newe deleted state.
2602: *
2603: * @param[in] bDeleted TRUE or FALSE
2604: *
2605: * @return HRESULT
2606: */
2607: public void setDeleted(boolean bDeleted) {
2608: IEditControlField pField = getNextField(null);
2609: while (pField != null) {
2610: pField.setDeleted(bDeleted);
2611: pField = getNextField(pField);
2612: }
2613: }
2614:
2615: /**
2616: * Set this translator's deleted state. All contained fields are set to the newe deleted state.
2617: *
2618: * @param[in] bDeleted TRUE or FALSE
2619: *
2620: * @return HRESULT
2621: */
2622: public void enableFields(boolean enableFields) {
2623: IEditControlField pField = getNextField(null);
2624: while (pField != null) {
2625: boolean enabled = pField.getEnabled();
2626: if (enabled) {
2627: // turn on the field's visibility AND set its text to its default if not empty
2628: pField.setVisible2(enableFields);
2629: }
2630: pField = getNextField(pField);
2631: }
2632: }
2633:
2634: private boolean handleLeadSeperator(IEditControlField pField,
2635: int nChar, int nCurrentPos) {
2636: boolean isHandled = false;
2637: int nStart = 0, nEnd = 0;
2638: if (pField != null) {
2639: nStart = pField.getFieldStartPos();
2640: nEnd = pField.getFieldEndPos();
2641: String leadSep = pField.getLeadSeparator();
2642:
2643: if (leadSep != null) {
2644: // if current pos is left of leading separator check it
2645: if (nCurrentPos <= (nStart + leadSep.length())) {
2646: isHandled = pField.isLeadSeparator(nChar);
2647: }
2648: }
2649: }
2650: return isHandled;
2651: }
2652:
2653: private ETPairT<Boolean, Boolean> handleSubFieldSeperator(
2654: IEditControlField pField, int nChar, int nCurrentPos) {
2655: boolean isHandled = false;
2656: boolean bSelectNextField = false;
2657: if (pField != null) {
2658: ITranslator pTrans = pField.getTranslator();
2659: if (pTrans != null) {
2660: ETPairT<Boolean, Boolean> retObj = pTrans
2661: .handleSeparator(nChar, nCurrentPos);
2662: isHandled = ((Boolean) retObj.getParamOne())
2663: .booleanValue();
2664: bSelectNextField = ((Boolean) retObj.getParamTwo())
2665: .booleanValue();
2666: if (isHandled) {
2667: if (bSelectNextField) {
2668: boolean visible = pField.getVisible();
2669: if (visible) {
2670: // found trailing separator, select following field
2671: pField = getNextVisibleField(pField);
2672: if (pField != null) {
2673: bSelectNextField = false;
2674: selectField(pField);
2675: }
2676: }
2677: }
2678: } else {
2679: // look for and handle delimitor
2680: isHandled = pTrans.handleDelimitor(nChar,
2681: nCurrentPos);
2682: }
2683: }
2684: }
2685: return new ETPairT<Boolean, Boolean>(
2686: Boolean.valueOf(isHandled), Boolean
2687: .valueOf(bSelectNextField));
2688: }
2689:
2690: private boolean handleTrailSeperator(IEditControlField pField,
2691: int nChar) {
2692: boolean bHandled = false;
2693:
2694: bHandled = pField.isTrailSeparator(nChar);
2695:
2696: return bHandled;
2697: }
2698:
2699: private boolean isDuplicateSeperator(IEditControlField pField,
2700: int nChar, int nCurrentPos) {
2701: boolean found = false;
2702: if (pField != null) {
2703: int nStart = pField.getFieldStartPos();
2704: int nEnd = pField.getFieldEndPos();
2705: //nEnd = pField.getFieldPos( nStart);
2706:
2707: if (nStart == nCurrentPos) // only counts at the beginning of a field
2708: {
2709: if (m_ParentField != null) {
2710: found = m_ParentField.isDelimitor(nChar);
2711: }
2712: }
2713: }
2714: return found;
2715: }
2716:
2717: /**
2718: * Gets the delimitor that should go before the translator's fields.
2719: * returns "" if the first field is specified.
2720: */
2721: private ETPairT<String, Boolean> getDelimitor(boolean firstField) {
2722: String delimiter = "";
2723: if (!firstField) {
2724: IEditControlField pParentField = getParentField();
2725: if (pParentField != null) {
2726: delimiter = pParentField.getDelimitor();
2727: if (delimiter == null) {
2728: delimiter = "";
2729: }
2730: }
2731: }
2732: firstField = false;
2733: return new ETPairT<String, Boolean>(delimiter, Boolean
2734: .valueOf(firstField));
2735: }
2736:
2737: private int getCurrentPosition() {
2738: int currentPos = 0;
2739: if (m_EditControl != null) {
2740: currentPos = m_EditControl.getCurrentPosition();
2741: }
2742: return currentPos;
2743: }
2744:
2745: private void createField(IEditControlField pLikeField,
2746: boolean insertBefore) {
2747: if (pLikeField != null) {
2748: IPropertyDefinition pDef = pLikeField
2749: .getPropertyDefinition();
2750: if (pDef != null) {
2751: IEditControlField pField = null;
2752: if (!insertBefore) {
2753: pLikeField = null;
2754: }
2755:
2756: pField = addFieldDefinition(pDef, pLikeField);
2757:
2758: // put_Visible was commented out, needed when inserting a multiplicity range
2759: pField.setVisible(true);
2760:
2761: // put enabled enables all eligible sub-fields
2762: pField.setEnabled(true);
2763: pField.setSelected(true);
2764:
2765: refreshEditControl();
2766: int nStart = pField.getTextStartPos();
2767: int nEnd = pField.getTextEndPos();
2768: //nEnd = pField.getTextPos(nStart);
2769:
2770: setSel(nStart, nStart);
2771: setCurrentPosition(nStart);
2772: }
2773: }
2774: }
2775:
2776: private boolean isOnDelimitor(int nChar) {
2777: boolean isDelimitor = false;
2778: if (m_ParentField != null) {
2779: isDelimitor = m_ParentField.isDelimitor(nChar);
2780: }
2781: return isDelimitor;
2782: }
2783:
2784: /**
2785: * Has this translator been modified?
2786: *
2787: * @param bModified[out]
2788: */
2789: public boolean getModified() {
2790: boolean retVal = false;
2791:
2792: // if modified return immediately, otherwise check for any nested translators
2793: if (m_Modified) {
2794: retVal = true;
2795: } else {
2796: IEditControlField pField = null;
2797:
2798: // get current field and offsets
2799: while ((pField = getNextField(pField)) != null) {
2800: // if field contains a translator, check it modified status
2801: retVal = pField.getModified();
2802: if (retVal) {
2803: break;
2804: }
2805: }
2806: }
2807: return retVal;
2808: }
2809:
2810: /**
2811: * Has this translator been modified?
2812: *
2813: * @param[in] bDeleted TRUE or FALSE
2814: *
2815: * @return HRESULT
2816: */
2817: public void setModified(boolean bModified) {
2818: if (m_ParentField != null) {
2819: m_ParentField.setModified(bModified);
2820: }
2821: if (m_EditControl != null) {
2822: m_EditControl.setModified(bModified);
2823: }
2824: m_Modified = bModified;
2825: }
2826:
2827: /**
2828: * Returns the text field that the caret is in. If the caret is past the last field the return is NULL.
2829: * If multiple fields exist at the current location, the return will be (in order of priority)
2830: * 1. The first enabled field. An enabled field can be edited, but may not be "visible" b/c it may be empty.
2831: * 2. The default field, whether visible or not.
2832: * 3. The first field, whether visible or not.
2833: *
2834: * @param [out,retval] An ITextField object, or NULL if the current position is past all fields contained by this translator.
2835: */
2836: public IEditControlField getCurrentField() {
2837: IEditControlField pField = null;
2838: IEditControlField pFirstFoundField = null;
2839: IEditControlField pDefaultField = null;
2840: if (m_TextFields != null) {
2841: int count = m_TextFields.size();
2842: for (int i = 0; i < count; i++) {
2843: pField = (IEditControlField) m_TextFields.elementAt(i);
2844: int startPos = pField.getFieldStartPos();
2845: int endPos = pField.getFieldEndPos();
2846: //endPos = pField.getFieldPos(startPos);
2847:
2848: // find a field that encompasses our current position
2849: if (getCurrentPosition() >= startPos
2850: && getCurrentPosition() <= endPos) {
2851: // store the first field found at this location
2852: if (pFirstFoundField == null) {
2853: pFirstFoundField = pField;
2854: }
2855:
2856: // store the first default field found at this location
2857: boolean bVal = false;
2858: if (pDefaultField == null) {
2859: bVal = pField.getDefault();
2860: if (bVal) {
2861: pDefaultField = pField;
2862: }
2863: }
2864:
2865: // return this field if enabled
2866: bVal = pField.getEnabled();
2867: if (bVal) {
2868: break;
2869: }
2870: }
2871: pField = null;
2872: }
2873:
2874: if (pField == null) {
2875: if (pDefaultField != null) {
2876: pField = pDefaultField;
2877: } else {
2878: pField = pFirstFoundField;
2879: }
2880: }
2881: }
2882: return pField;
2883: }
2884:
2885: private IEditControlField jumpToNextField() {
2886: IEditControlField retField = null;
2887:
2888: retField = getCurrentField();
2889: if (retField == null) {
2890: retField = getNextField(null);
2891: }
2892: // now look for a succeeding field, if found we select it
2893: retField = getNextField(retField);
2894:
2895: if (retField != null) {
2896: selectField(retField);
2897: }
2898:
2899: return retField;
2900: }
2901:
2902: /**
2903: * Places the caret at the end of the text field preceeding this one.
2904: *
2905: * @param pNext[in]
2906: */
2907: private IEditControlField jumpToPreviousField(
2908: IEditControlField pNext) {
2909: IEditControlField retField = getPreviousField(pNext);
2910:
2911: if (retField != null) {
2912: int startPos = retField.getTextStartPos();
2913: int endPos = retField.getTextEndPos();
2914: //endPos = retField.getTextPos(startPos);
2915: setPosition(endPos);
2916: }
2917:
2918: return retField;
2919: }
2920:
2921: /**
2922: * Places the caret at the beginnning of this field.
2923: *
2924: * @param pField[in]
2925: */
2926: private void jumpToFieldBegin(IEditControlField pField) {
2927: if (pField != null) {
2928: int startPos = pField.getTextStartPos();
2929: int endPos = pField.getTextEndPos();
2930: //endPos = pField.getTextPos(startPos);
2931: setPosition(startPos);
2932: }
2933: }
2934:
2935: /**
2936: * Places the caret at the end of this field.
2937: *
2938: * @param pField[in]
2939: */
2940: private void jumpToFieldEnd(IEditControlField pField) {
2941: if (pField != null) {
2942: int startPos = pField.getTextStartPos();
2943: int endPos = pField.getTextEndPos();
2944: //endPos = pField.getTextPos(startPos);
2945: setPosition(endPos);
2946: }
2947: }
2948:
2949: /**
2950: * Registers acclerators for our delimitors
2951: *
2952: * @return HRESULT
2953: */
2954: public void registerAccelerators() {
2955: if (m_EditControl != null) {
2956: // let the current field have first crack at it, this may be a delimitor for it
2957: if (m_ParentField != null) {
2958: // we have a delimitor! Extract the character
2959: String sDelim = m_ParentField.getDelimitor();
2960: if (sDelim != null && sDelim.length() > 0) {
2961: int length = sDelim.length();
2962: for (int i = 0; i < length; i++) {
2963: char c = sDelim.charAt(i);
2964: if (c != ' ') {
2965: // create an accelerator with Ctrl + character
2966: m_EditControl.registerAccelerator(c,
2967: KeyEvent.VK_CONTROL);
2968: }
2969: }
2970: }
2971: }
2972:
2973: // for each sub-field, ask it to handle delimitors
2974: IEditControlField pField = null;
2975: while ((pField = getNextField(pField)) != null) {
2976: ITranslator pTrans = pField.getTranslator();
2977: if (pTrans != null) {
2978: pTrans.registerAccelerators();
2979: }
2980: }
2981: }
2982: }
2983:
2984: /**
2985: * Handles an accelerator detected by the edit control. Accelerators are registered by calling
2986: * RegisterAccelerators().
2987: *
2988: * @param[in] nID The application-defined identifier for this accelerator.
2989: *
2990: * @return HRESULT
2991: */
2992: public boolean handleAccelerator(int nChar) {
2993: boolean isHandled = false;
2994: isHandled = handleDelimitor(nChar, getCurrentPosition());
2995:
2996: if (!isHandled) {
2997: // for each sub-field, ask it to handle delimitors
2998: IEditControlField pField = null;
2999: while ((pField = getNextField(pField)) != null
3000: && !isHandled) {
3001: ITranslator pTrans = pField.getTranslator();
3002: if (pTrans != null) {
3003: isHandled = pTrans.handleDelimitor(nChar,
3004: getCurrentPosition());
3005: }
3006: }
3007: }
3008: return isHandled;
3009: }
3010:
3011: /* (non-Javadoc)
3012: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getTextStartPos()
3013: */
3014: public int getTextStartPos() {
3015: int retStart = 0;
3016: // read first field, obtain starting position
3017: IEditControlField pField = getNextField(null);
3018: if (pField != null) {
3019: retStart = pField.getTextStartPos();
3020: }
3021:
3022: return retStart;
3023: }
3024:
3025: /* (non-Javadoc)
3026: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getTextEndPos()
3027: */
3028: public int getTextEndPos() {
3029: int retEnd = 0;
3030: // read first field, obtain starting position
3031: IEditControlField pField = getNextField(null);
3032: if (pField != null) {
3033: retEnd = pField.getTextEndPos();
3034: }
3035:
3036: // loop until no more visible fields, updating ending position
3037: while ((pField = getNextField(pField)) != null) {
3038: retEnd = pField.getTextEndPos();
3039: }
3040: return retEnd;
3041: }
3042:
3043: public int getLastTextStartPos() {
3044: int retStart = 0;
3045: // read first field, obtain starting position
3046: IEditControlField pField = getLastField();
3047: while (pField != null) {
3048: if (pField != null && pField.getVisible()) {
3049: retStart = pField.getTextStartPos();
3050: break;
3051: }
3052: pField = getPreviousField(pField);
3053: }
3054:
3055: //if none of the fields are visible yet, we need to pass back the start position of current field
3056: if (retStart == 0) {
3057: pField = getFirstField();
3058: retStart = pField.getTextStartPos();
3059: }
3060:
3061: return retStart;
3062: }
3063:
3064: /* (non-Javadoc)
3065: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getFieldStartPos()
3066: */
3067: public int getFieldStartPos() {
3068: int retPos = 0;
3069: IEditControlField pField = getNextField(null);
3070: if (pField != null) {
3071: retPos = pField.getFieldStartPos();
3072: }
3073: return retPos;
3074: }
3075:
3076: /* (non-Javadoc)
3077: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getFieldEndPos()
3078: */
3079: public int getFieldEndPos() {
3080: int retPos = 0;
3081: IEditControlField pField = getNextField(null);
3082: if (pField != null) {
3083: retPos = pField.getFieldEndPos();
3084: // hidden fields will return nStartPos == nEndPos so account for no text width
3085: int dummy = 0;
3086: while ((pField = getNextField(pField)) != null) {
3087: retPos = pField.getFieldEndPos();
3088: }
3089: }
3090: return retPos;
3091: }
3092:
3093: /* (non-Javadoc)
3094: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getTooltipLetText()
3095: */
3096: public String getTooltipLeftText() {
3097: if (!m_IsGetToolTipText) {
3098: getTooltipText();
3099: m_IsGetToolTipText = true;
3100: }
3101: return m_TooltipLeftText;
3102: }
3103:
3104: /* (non-Javadoc)
3105: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getTooltipSubjectText()
3106: */
3107: public String getTooltipSubjectText() {
3108: if (!m_IsGetToolTipText) {
3109: getTooltipText();
3110: m_IsGetToolTipText = true;
3111: }
3112: return m_TooltipSubjectText;
3113: }
3114:
3115: /* (non-Javadoc)
3116: * @see org.netbeans.modules.uml.ui.controls.editcontrol.ITranslator#getTooltipRightText()
3117: */
3118: public String getTooltipRightText() {
3119: if (!m_IsGetToolTipText) {
3120: getTooltipText();
3121: m_IsGetToolTipText = true;
3122: }
3123: return m_TooltipRightText;
3124: }
3125:
3126: public boolean handleDelete(boolean deleteRightwards) {
3127: boolean retVal = false;
3128: try {
3129: IEditControlField pField = null;
3130: int nStart = 0;
3131: int nEnd = 0;
3132:
3133: // get selected area
3134: int nStartPos = getSelStartPos();
3135: int nEndPos = getSelEndPos();
3136:
3137: // test if anything's currently selected
3138: if (nStartPos == nEndPos) {
3139: // nothing is selected, delete only 1 text character
3140: pField = getCurrentField();
3141: if (pField != null) {
3142: // sanity check, we should never enter this routine for a field that contains sub-fields
3143: ITranslator pTrans = pField.getTranslator();
3144: if (pTrans != null) {
3145: // if we are on one of the separators, handle it as an arrow key
3146: boolean handled = handleKeyDown(deleteRightwards ? KeyEvent.VK_RIGHT
3147: : KeyEvent.VK_LEFT);
3148: return true;
3149: }
3150:
3151: // can only delete within text boundaries
3152: nStart = pField.getTextStartPos();
3153: nEnd = pField.getTextEndPos();
3154: if (nStartPos >= nStart && nStartPos <= nEnd) {
3155: if (deleteRightwards) {
3156: // going right, delete up to end of field
3157: nEndPos = (nEnd < nEndPos + 1) ? nEnd
3158: : nEndPos + 1;
3159: } else {
3160: // special case, field is empty and they're deleting the leading separator
3161: if (nStart == nEnd) {
3162: pField.setVisible(false);
3163: nStart = pField.getFieldStartPos();
3164: nEnd = pField.getFieldEndPos();
3165: updateVisibleFields(m_ParentField);
3166: refreshEditControl();
3167: setPosition(nStart);
3168: retVal = true;
3169: }
3170: // going left, delete up to beginning of field
3171: nStartPos = (nStart > nStartPos - 1) ? nStart
3172: : nStartPos - 1;
3173: }
3174: }
3175: // do the delete
3176: if (!retVal) {
3177: retVal = true;
3178: if (nStartPos != nEndPos) {
3179: replaceText(pField, nStartPos, nEndPos, "",
3180: true);
3181: }
3182: }
3183: }
3184: } else {
3185: // here we try to determine if the selected area crosses field boundaries
3186: // if crossing a boundary(s) all text within the visible fields must be selected
3187:
3188: // find our starting and ending fields
3189: IEditControlField pFirstField = getFieldAtPosition(nStartPos);
3190: IEditControlField pLastField = getFieldAtPosition(nEndPos);
3191:
3192: // if either field is null we can't handle here, in which case it goes back up to the parent
3193: // translator
3194: if (pFirstField != null && pLastField != null) {
3195: boolean bDelete = (pFirstField.equals(pLastField));
3196: if (bDelete) {
3197: // selected area is within a single field, handle normally
3198: replaceText(pFirstField, nStartPos, nEndPos,
3199: "", true);
3200: setCurrentPosition(nStartPos);
3201: retVal = true;
3202: } else {
3203: // spanning multiple fields, make sure each is entirely selected
3204: nStart = pFirstField.getTextStartPos();
3205: nEnd = pFirstField.getTextEndPos();
3206:
3207: // test if any part of the field is selected (might not be)
3208: if (nStartPos >= nEnd || nEndPos <= nStart) {
3209: pFirstField = getNextVisibleField(pFirstField);
3210:
3211: }
3212:
3213: // assume the last field can't have this happen
3214: bDelete = true;
3215: pField = pFirstField;
3216: while (pField != null) {
3217: nStart = pField.getTextStartPos();
3218: nEnd = pField.getTextEndPos();
3219:
3220: // test if all of the field is selected
3221: if ((nStartPos < nEnd && nStartPos > nStart)
3222: || (nEndPos > nStart && nEndPos < nEnd)) {
3223: // nope, don't allow delete
3224: bDelete = false;
3225: break;
3226: }
3227: if (pField.equals(pLastField)) {
3228: break;
3229: }
3230: pField = getNextVisibleField(pField);
3231: }
3232:
3233: // spanning multiple fields, make sure each is entirely selected
3234: bDelete = true;
3235: pField = pFirstField;
3236: while (pField != null) {
3237: nStart = pField.getTextStartPos();
3238: nEnd = pField.getTextEndPos();
3239:
3240: // test if any part of the field is selected (might not be)
3241: if (nStartPos >= nEnd || nEndPos <= nStart) {
3242: // field is not selected, toss it from our survey
3243: }
3244: if ((nStartPos < nEnd && nStartPos > nStart)
3245: || (nEndPos > nStart && nEndPos < nEnd)) {
3246: bDelete = false;
3247: break;
3248: }
3249: if (pField.equals(pLastField)) {
3250: break;
3251: }
3252: pField = getNextVisibleField(pField);
3253: }
3254:
3255: // if all fields are selected delete them
3256: if (bDelete) {
3257: pField = pFirstField;
3258: while (pField != null) {
3259: pField.setDeleted(true);
3260: if (pField.equals(pLastField)) {
3261: break;
3262: }
3263: pField = getNextVisibleField(pField);
3264: }
3265:
3266: setCurrentPosition(nStartPos);
3267: refreshEditControl();
3268: setModified(true);
3269: retVal = true;
3270: } else {
3271:
3272: }
3273: }
3274: }
3275: }
3276: } catch (Exception e) {
3277: Log.stackTrace(e);
3278: }
3279: return retVal;
3280: }
3281:
3282: /**
3283: * Moves caret and selects text from either the current position
3284: * or the currently selected text. Text is selected if ShiftDown is TRUE.
3285: */
3286: private void selectToPosition(int nPos) {
3287: try {
3288: int nStartPos = getSelStartPos();
3289: int nEndPos = getSelEndPos();
3290:
3291: // use control key status to determine if selecting
3292: if (shiftDown()) {
3293: if (getCurrentPosition() == nStartPos) {
3294: // moving left side
3295: nStartPos = nPos;
3296: } else {
3297: // moving right side
3298: nEndPos = nPos;
3299: }
3300: } else {
3301: // no shift, just move cursor
3302: nStartPos = nPos;
3303: nEndPos = nPos;
3304: }
3305: setCurrentPosition(nPos);
3306: setSel(nStartPos, nEndPos);
3307: if (m_EditControl != null) {
3308: updateHints();
3309: }
3310: } catch (Exception e) {
3311: Log.stackTrace(e);
3312: }
3313: }
3314:
3315: private boolean shiftDown() {
3316: return m_EditControl.isShiftDown();
3317: }
3318:
3319: private boolean controlDown() {
3320: return m_EditControl.isControlDown();
3321: }
3322: }
|