1774424394537c69975f8fc0044765db8c252f66fTor Norbye/* 2774424394537c69975f8fc0044765db8c252f66fTor Norbye * Copyright (C) 2012 The Android Open Source Project 3774424394537c69975f8fc0044765db8c252f66fTor Norbye * 4774424394537c69975f8fc0044765db8c252f66fTor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5774424394537c69975f8fc0044765db8c252f66fTor Norbye * you may not use this file except in compliance with the License. 6774424394537c69975f8fc0044765db8c252f66fTor Norbye * You may obtain a copy of the License at 7774424394537c69975f8fc0044765db8c252f66fTor Norbye * 8774424394537c69975f8fc0044765db8c252f66fTor Norbye * http://www.eclipse.org/org/documents/epl-v10.php 9774424394537c69975f8fc0044765db8c252f66fTor Norbye * 10774424394537c69975f8fc0044765db8c252f66fTor Norbye * Unless required by applicable law or agreed to in writing, software 11774424394537c69975f8fc0044765db8c252f66fTor Norbye * distributed under the License is distributed on an "AS IS" BASIS, 12774424394537c69975f8fc0044765db8c252f66fTor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13774424394537c69975f8fc0044765db8c252f66fTor Norbye * See the License for the specific language governing permissions and 14774424394537c69975f8fc0044765db8c252f66fTor Norbye * limitations under the License. 15774424394537c69975f8fc0044765db8c252f66fTor Norbye */ 16774424394537c69975f8fc0044765db8c252f66fTor Norbyepackage com.android.ide.eclipse.adt.internal.editors.layout.properties; 17774424394537c69975f8fc0044765db8c252f66fTor Norbye 1812d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_TEXT_SIZE; 1912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.PREFIX_RESOURCE_REF; 2012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.PREFIX_THEME_REF; 2112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.UNIT_DP; 2212d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.UNIT_SP; 2312d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.VALUE_FALSE; 2412d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.VALUE_TRUE; 25774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.BOOLEAN; 26774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.DIMENSION; 27774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.ENUM; 28774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.FLAG; 29774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.FLOAT; 30774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.INTEGER; 31774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.REFERENCE; 32774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.STRING; 33774424394537c69975f8fc0044765db8c252f66fTor Norbye 34774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.annotations.NonNull; 35774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.annotations.Nullable; 36774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.ide.common.api.IAttributeInfo; 37774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.ide.common.api.IAttributeInfo.Format; 38774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; 39774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; 401fb460987f7d832adf12290f41448d0c16a95972Siva Velusamyimport com.android.utils.SdkUtils; 41774424394537c69975f8fc0044765db8c252f66fTor Norbye 42774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport org.eclipse.jface.fieldassist.ContentProposal; 43774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport org.eclipse.jface.fieldassist.IContentProposal; 44774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport org.eclipse.jface.fieldassist.IContentProposalProvider; 45774424394537c69975f8fc0044765db8c252f66fTor Norbye 46774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport java.util.ArrayList; 47774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport java.util.EnumSet; 48774424394537c69975f8fc0044765db8c252f66fTor Norbyeimport java.util.List; 49774424394537c69975f8fc0044765db8c252f66fTor Norbye 50774424394537c69975f8fc0044765db8c252f66fTor Norbye/** 51774424394537c69975f8fc0044765db8c252f66fTor Norbye * An {@link IContentProposalProvider} which completes possible property values 52774424394537c69975f8fc0044765db8c252f66fTor Norbye * for Android properties, completing resource strings, flag values, enum 53774424394537c69975f8fc0044765db8c252f66fTor Norbye * values, as well as dimension units. 54774424394537c69975f8fc0044765db8c252f66fTor Norbye */ 55774424394537c69975f8fc0044765db8c252f66fTor Norbyeabstract class ValueCompleter implements IContentProposalProvider { 56774424394537c69975f8fc0044765db8c252f66fTor Norbye @Nullable 57774424394537c69975f8fc0044765db8c252f66fTor Norbye protected abstract CommonXmlEditor getEditor(); 58774424394537c69975f8fc0044765db8c252f66fTor Norbye 59774424394537c69975f8fc0044765db8c252f66fTor Norbye @NonNull 60774424394537c69975f8fc0044765db8c252f66fTor Norbye protected abstract AttributeDescriptor getDescriptor(); 61774424394537c69975f8fc0044765db8c252f66fTor Norbye 62774424394537c69975f8fc0044765db8c252f66fTor Norbye @Override 63774424394537c69975f8fc0044765db8c252f66fTor Norbye public IContentProposal[] getProposals(String contents, int position) { 64774424394537c69975f8fc0044765db8c252f66fTor Norbye AttributeDescriptor descriptor = getDescriptor(); 65774424394537c69975f8fc0044765db8c252f66fTor Norbye IAttributeInfo info = descriptor.getAttributeInfo(); 66774424394537c69975f8fc0044765db8c252f66fTor Norbye EnumSet<Format> formats = info.getFormats(); 67774424394537c69975f8fc0044765db8c252f66fTor Norbye 68774424394537c69975f8fc0044765db8c252f66fTor Norbye List<IContentProposal> proposals = new ArrayList<IContentProposal>(); 69774424394537c69975f8fc0044765db8c252f66fTor Norbye 70774424394537c69975f8fc0044765db8c252f66fTor Norbye String prefix = contents; // TODO: Go back to position inside the array? 71774424394537c69975f8fc0044765db8c252f66fTor Norbye 72774424394537c69975f8fc0044765db8c252f66fTor Norbye // TODO: If the user is typing in a number, or a number plus a prefix of a dimension unit, 73774424394537c69975f8fc0044765db8c252f66fTor Norbye // then propose that number plus the completed dimension unit (using sp for text, dp 74774424394537c69975f8fc0044765db8c252f66fTor Norbye // for other properties and maybe both if I'm not sure) 75774424394537c69975f8fc0044765db8c252f66fTor Norbye if (formats.contains(STRING) 76774424394537c69975f8fc0044765db8c252f66fTor Norbye && !contents.isEmpty() 77774424394537c69975f8fc0044765db8c252f66fTor Norbye && (formats.size() > 1 && formats.contains(REFERENCE) || 78774424394537c69975f8fc0044765db8c252f66fTor Norbye formats.size() > 2) 79774424394537c69975f8fc0044765db8c252f66fTor Norbye && !contents.startsWith(PREFIX_RESOURCE_REF) 80774424394537c69975f8fc0044765db8c252f66fTor Norbye && !contents.startsWith(PREFIX_THEME_REF)) { 81774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(contents)); 82774424394537c69975f8fc0044765db8c252f66fTor Norbye } 83774424394537c69975f8fc0044765db8c252f66fTor Norbye 84774424394537c69975f8fc0044765db8c252f66fTor Norbye if (!contents.isEmpty() && Character.isDigit(contents.charAt(0)) 85774424394537c69975f8fc0044765db8c252f66fTor Norbye && (formats.contains(DIMENSION) 86774424394537c69975f8fc0044765db8c252f66fTor Norbye || formats.contains(INTEGER) 87774424394537c69975f8fc0044765db8c252f66fTor Norbye || formats.contains(FLOAT))) { 88774424394537c69975f8fc0044765db8c252f66fTor Norbye StringBuilder sb = new StringBuilder(); 89774424394537c69975f8fc0044765db8c252f66fTor Norbye for (int i = 0, n = contents.length(); i < n; i++) { 90774424394537c69975f8fc0044765db8c252f66fTor Norbye char c = contents.charAt(i); 91774424394537c69975f8fc0044765db8c252f66fTor Norbye if (Character.isDigit(c)) { 92774424394537c69975f8fc0044765db8c252f66fTor Norbye sb.append(c); 93774424394537c69975f8fc0044765db8c252f66fTor Norbye } else { 94774424394537c69975f8fc0044765db8c252f66fTor Norbye break; 95774424394537c69975f8fc0044765db8c252f66fTor Norbye } 96774424394537c69975f8fc0044765db8c252f66fTor Norbye } 97774424394537c69975f8fc0044765db8c252f66fTor Norbye 98774424394537c69975f8fc0044765db8c252f66fTor Norbye String number = sb.toString(); 99774424394537c69975f8fc0044765db8c252f66fTor Norbye if (formats.contains(Format.DIMENSION)) { 100774424394537c69975f8fc0044765db8c252f66fTor Norbye if (descriptor.getXmlLocalName().equals(ATTR_TEXT_SIZE)) { 101774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(number + UNIT_SP)); 102774424394537c69975f8fc0044765db8c252f66fTor Norbye } 103774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(number + UNIT_DP)); 104774424394537c69975f8fc0044765db8c252f66fTor Norbye } else if (formats.contains(Format.INTEGER)) { 105774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(number)); 106774424394537c69975f8fc0044765db8c252f66fTor Norbye } 107774424394537c69975f8fc0044765db8c252f66fTor Norbye // Perhaps offer other units too -- see AndroidContentAssist.sDimensionUnits 108774424394537c69975f8fc0044765db8c252f66fTor Norbye } 109774424394537c69975f8fc0044765db8c252f66fTor Norbye 110774424394537c69975f8fc0044765db8c252f66fTor Norbye if (formats.contains(REFERENCE) || contents.startsWith(PREFIX_RESOURCE_REF) 111774424394537c69975f8fc0044765db8c252f66fTor Norbye || contents.startsWith(PREFIX_THEME_REF)) { 112774424394537c69975f8fc0044765db8c252f66fTor Norbye CommonXmlEditor editor = getEditor(); 113774424394537c69975f8fc0044765db8c252f66fTor Norbye if (editor != null) { 114774424394537c69975f8fc0044765db8c252f66fTor Norbye String[] matches = ResourceValueCompleter.computeResourceStringMatches( 115774424394537c69975f8fc0044765db8c252f66fTor Norbye editor, 116774424394537c69975f8fc0044765db8c252f66fTor Norbye descriptor, contents.substring(0, position)); 117774424394537c69975f8fc0044765db8c252f66fTor Norbye for (String match : matches) { 118774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(match)); 119774424394537c69975f8fc0044765db8c252f66fTor Norbye } 120774424394537c69975f8fc0044765db8c252f66fTor Norbye } 121774424394537c69975f8fc0044765db8c252f66fTor Norbye } 122774424394537c69975f8fc0044765db8c252f66fTor Norbye 123774424394537c69975f8fc0044765db8c252f66fTor Norbye if (formats.contains(FLAG)) { 124774424394537c69975f8fc0044765db8c252f66fTor Norbye String[] values = info.getFlagValues(); 125774424394537c69975f8fc0044765db8c252f66fTor Norbye if (values != null) { 126774424394537c69975f8fc0044765db8c252f66fTor Norbye // Flag completion 127774424394537c69975f8fc0044765db8c252f66fTor Norbye int flagStart = prefix.lastIndexOf('|'); 128774424394537c69975f8fc0044765db8c252f66fTor Norbye String prepend = null; 129774424394537c69975f8fc0044765db8c252f66fTor Norbye if (flagStart != -1) { 130774424394537c69975f8fc0044765db8c252f66fTor Norbye prepend = prefix.substring(0, flagStart + 1); 131774424394537c69975f8fc0044765db8c252f66fTor Norbye prefix = prefix.substring(flagStart + 1).trim(); 132774424394537c69975f8fc0044765db8c252f66fTor Norbye } 133774424394537c69975f8fc0044765db8c252f66fTor Norbye 134774424394537c69975f8fc0044765db8c252f66fTor Norbye boolean exactMatch = false; 135774424394537c69975f8fc0044765db8c252f66fTor Norbye for (String value : values) { 136774424394537c69975f8fc0044765db8c252f66fTor Norbye if (prefix.equals(value)) { 137774424394537c69975f8fc0044765db8c252f66fTor Norbye exactMatch = true; 138774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(contents)); 139774424394537c69975f8fc0044765db8c252f66fTor Norbye 140774424394537c69975f8fc0044765db8c252f66fTor Norbye break; 141774424394537c69975f8fc0044765db8c252f66fTor Norbye } 142774424394537c69975f8fc0044765db8c252f66fTor Norbye } 143774424394537c69975f8fc0044765db8c252f66fTor Norbye 144774424394537c69975f8fc0044765db8c252f66fTor Norbye if (exactMatch) { 145774424394537c69975f8fc0044765db8c252f66fTor Norbye prepend = contents + '|'; 146774424394537c69975f8fc0044765db8c252f66fTor Norbye prefix = ""; 147774424394537c69975f8fc0044765db8c252f66fTor Norbye } 148774424394537c69975f8fc0044765db8c252f66fTor Norbye 149774424394537c69975f8fc0044765db8c252f66fTor Norbye for (String value : values) { 1501fb460987f7d832adf12290f41448d0c16a95972Siva Velusamy if (SdkUtils.startsWithIgnoreCase(value, prefix)) { 151774424394537c69975f8fc0044765db8c252f66fTor Norbye if (prepend != null && prepend.contains(value)) { 152774424394537c69975f8fc0044765db8c252f66fTor Norbye continue; 153774424394537c69975f8fc0044765db8c252f66fTor Norbye } 154774424394537c69975f8fc0044765db8c252f66fTor Norbye String match; 155774424394537c69975f8fc0044765db8c252f66fTor Norbye if (prepend != null) { 156774424394537c69975f8fc0044765db8c252f66fTor Norbye match = prepend + value; 157774424394537c69975f8fc0044765db8c252f66fTor Norbye } else { 158774424394537c69975f8fc0044765db8c252f66fTor Norbye match = value; 159774424394537c69975f8fc0044765db8c252f66fTor Norbye } 160774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(match)); 161774424394537c69975f8fc0044765db8c252f66fTor Norbye } 162774424394537c69975f8fc0044765db8c252f66fTor Norbye } 163774424394537c69975f8fc0044765db8c252f66fTor Norbye } 164774424394537c69975f8fc0044765db8c252f66fTor Norbye } else if (formats.contains(ENUM)) { 165774424394537c69975f8fc0044765db8c252f66fTor Norbye String[] values = info.getEnumValues(); 166774424394537c69975f8fc0044765db8c252f66fTor Norbye if (values != null) { 167774424394537c69975f8fc0044765db8c252f66fTor Norbye for (String value : values) { 1681fb460987f7d832adf12290f41448d0c16a95972Siva Velusamy if (SdkUtils.startsWithIgnoreCase(value, prefix)) { 169774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(value)); 170774424394537c69975f8fc0044765db8c252f66fTor Norbye } 171774424394537c69975f8fc0044765db8c252f66fTor Norbye } 172774424394537c69975f8fc0044765db8c252f66fTor Norbye 173774424394537c69975f8fc0044765db8c252f66fTor Norbye for (String value : values) { 1741fb460987f7d832adf12290f41448d0c16a95972Siva Velusamy if (!SdkUtils.startsWithIgnoreCase(value, prefix)) { 175774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(value)); 176774424394537c69975f8fc0044765db8c252f66fTor Norbye } 177774424394537c69975f8fc0044765db8c252f66fTor Norbye } 178774424394537c69975f8fc0044765db8c252f66fTor Norbye } 179774424394537c69975f8fc0044765db8c252f66fTor Norbye } else if (formats.contains(BOOLEAN)) { 180774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(VALUE_TRUE)); 181774424394537c69975f8fc0044765db8c252f66fTor Norbye proposals.add(new ContentProposal(VALUE_FALSE)); 182774424394537c69975f8fc0044765db8c252f66fTor Norbye } 183774424394537c69975f8fc0044765db8c252f66fTor Norbye 184774424394537c69975f8fc0044765db8c252f66fTor Norbye return proposals.toArray(new IContentProposal[proposals.size()]); 185774424394537c69975f8fc0044765db8c252f66fTor Norbye } 18612d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye} 187