001: /*******************************************************************************
002: * Copyright (c) 2006, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.util;
011:
012: import java.util.HashSet;
013:
014: import org.eclipse.swt.widgets.Control;
015: import org.eclipse.swt.widgets.Label;
016:
017: /**
018: * PDELabelUtility
019: *
020: */
021: public class PDELabelUtility {
022:
023: /**
024: * Get the field label text from the label widget created before the
025: * control (assumption). Use this method when the control's label is
026: * variable or if the label's text is set elsewhere. Note: Hyperlink
027: * label text will not be detected.
028: * @param control
029: * @return
030: */
031: public static String getFieldLabel(Control control) {
032: // Note: Does not handle hyperlink labels
033:
034: // Get the children of the control's parent
035: // The control itself should be in there
036: // Assuming the control's label is in there as well
037: Control[] controls = control.getParent().getChildren();
038: // Ensure has controls
039: if (controls.length == 0) {
040: return null;
041: }
042: // Me = control
043: // Track the index of myself
044: int myIndex = -1;
045: // Linearly search controls for myself
046: for (int i = 0; i < controls.length; i++) {
047: if (controls[i] == control) {
048: // Found myself
049: myIndex = i;
050: break;
051: }
052: }
053: // Ensure I was found and am not the first widget
054: if (myIndex <= 0) {
055: return null;
056: }
057: // Assume label is the control created before me
058: int labelIndex = myIndex - 1;
059: // Ensure the label index points to a label
060: if ((controls[labelIndex] instanceof Label) == false) {
061: return null;
062: }
063: // Get the label text
064: String labelText = ((Label) controls[labelIndex]).getText();
065: // Get rid of the trailing colon (if any)
066: int colonIndex = labelText.indexOf(':');
067: if (colonIndex >= 0) {
068: labelText = labelText.replaceAll(":", ""); //$NON-NLS-1$ //$NON-NLS-2$
069: }
070: // Get rid of mnemonics (if any)
071: int ampIndex = labelText.indexOf('&');
072: if (ampIndex >= 0) {
073: labelText = labelText.replaceAll("&", ""); //$NON-NLS-1$ //$NON-NLS-2$
074: }
075:
076: return labelText;
077: }
078:
079: /**
080: * @param qualification
081: * @param message
082: * @return
083: */
084: public static String qualifyMessage(String qualification,
085: String message) {
086: StringBuffer buffer = new StringBuffer();
087: buffer.append(qualification);
088: buffer.append(':');
089: buffer.append(' ');
090: buffer.append(message);
091: return buffer.toString();
092: }
093:
094: /**
095: * @param base
096: * @param set
097: */
098: private static void addNumberToBase(StringBuffer base,
099: boolean bracketed, HashSet set) {
100: if (set.size() > 0) {
101: // Limit on the number of auto-generated item numbers to check for
102: int limit = 100;
103: // Check the set for the numbers encountered and generate the
104: // lowest number accordingly
105: if (set.contains(new Integer(0)) == false) {
106: // Use base
107: } else {
108: for (int x = 1; x < limit; x++) {
109: // Check if the number was already used to auto-generate an
110: // existing item
111: if (set.contains(new Integer(x)) == false) {
112: if (bracketed)
113: base.append(" ("); //$NON-NLS-1$
114: base.append(x);
115: if (bracketed)
116: base.append(")"); //$NON-NLS-1$
117: break;
118: }
119: }
120: }
121: }
122: }
123:
124: /**
125: * @param base
126: * @param set
127: * @param title
128: */
129: private static void compareTitleWithBase(String base,
130: boolean bracketed, HashSet set, String title) {
131: // Check to see it the name starts with the prefix
132: if (title.toLowerCase().startsWith(base.toLowerCase())) {
133: // with brackets add on is: space, (, #, )
134: int minSizeNumAddOn = 4;
135: if (!bracketed)
136: // without brackets and space add on is just number
137: minSizeNumAddOn = 1;
138: // We found a possible auto-generated name
139: // Determine number
140: if (title.length() >= (base.length() + minSizeNumAddOn)) {
141: String numPart;
142: if (bracketed && title.charAt(base.length()) == ' ') {
143: // We skipped the space since we already checked
144: numPart = title.substring(base.length() + 1);
145: } else if (!bracketed) {
146: // without brackets, the numPart is everything after the prefix
147: numPart = title.substring(base.length());
148: } else {
149: // We are using brackets and there was no space
150: return;
151: }
152: if (bracketed) {
153: if (numPart.charAt(0) == '(') {
154: // We are using brackets and confirmed that the open bracket exists
155: // move on to just the number part
156: numPart = numPart.substring(1);
157: } else {
158: // We are using brackets and there is no opening bracket
159: return;
160: }
161: }
162: // We found an auto-generated name
163: StringBuffer buffer = new StringBuffer();
164: // Parse the number between the brackets
165: for (int j = 0; j < numPart.length(); j++) {
166: char current = numPart.charAt(j);
167: // Make sure its a digit
168: if (Character.isDigit(current)) {
169: buffer.append(current);
170: } else {
171: if (!bracketed || numPart.charAt(j) != ')'
172: || j != numPart.length() - 1) {
173: // without brackets, a non digits means this will not conflict
174: // with brackets, anything other than a ')' means this will not conflict
175: // with brackets, if this is not the last character it will not conflict
176: return;
177: }
178: // if all conditions passed, this is the last loop, no need to break
179: }
180: }
181: // Convert the number we found into an actual number
182: if (buffer.length() > 0) {
183: set.add(new Integer(buffer.toString()));
184: }
185:
186: } else {
187: // No number to parse
188: // Assume it is just base
189: set.add(new Integer(0));
190: }
191: }
192: }
193:
194: /**
195: * @return
196: */
197: public static String generateName(String[] names, String base) {
198: return generateName(names, base, true);
199: }
200:
201: /**
202: * <p>Generates a name that does not conflict with any of the given names with one of two forms:
203: * <ol><li>"<base> (#)"</li><li>"<base>#"</li></ol>
204: * The number will be omitted if the base name alone is available.</p>
205: *
206: * @param names
207: * the existing names that should not be conflicted
208: * @param base
209: * the base name to add numbers to
210: * @param bracketed
211: * if true use the first form, otherwise use the second
212: * @return
213: * the non-conflicting name
214: */
215: public static String generateName(String[] names, String base,
216: boolean bracketed) {
217: StringBuffer result = new StringBuffer(base);
218: // Used to track auto-generated numbers used
219: HashSet set = new HashSet();
220:
221: // Linear search O(n).
222: // Performance hit unnoticeable because number of items per cheatsheet
223: // should be minimal.
224: for (int i = 0; i < names.length; i++) {
225: PDELabelUtility.compareTitleWithBase(base, bracketed, set,
226: names[i]);
227: }
228: // Add an auto-generated number
229: PDELabelUtility.addNumberToBase(result, bracketed, set);
230:
231: return result.toString();
232: }
233:
234: // Gets the base from a name that was generated by the generateName method.
235: public static String getBaseName(String name, boolean bracketed) {
236: String result = name;
237: if (bracketed) {
238: if (result.charAt(result.length() - 1) != ')')
239: return name;
240: result = result.substring(0, result.length() - 1);
241: }
242: while (Character.isDigit(result.charAt(result.length() - 1)))
243: result = result.substring(0, result.length() - 1);
244: if (bracketed) {
245: if (!result.substring(result.length() - 2).equals(" (")) //$NON-NLS-1$
246: return name;
247: result = result.substring(0, result.length() - 2);
248: }
249: return result;
250: }
251: }
|