/* * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.android.designer.propertyTable; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.propertyTable.editors.StringsComboEditor; import com.intellij.designer.model.Property; import com.intellij.designer.propertyTable.PropertyEditor; import com.intellij.designer.propertyTable.PropertyRenderer; import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.util.ArrayUtil; import org.jetbrains.android.dom.attrs.AttributeDefinition; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * @author Alexander Lobas */ public class GravityProperty extends FlagProperty { private static final String[] CENTER = {"center_horizontal", "center_vertical", "center"}; private static final String[] FILL = {"fill_horizontal", "fill_vertical", "fill"}; private static final String[] CLIP = {"clip_horizontal", "clip_vertical"}; private static final String[] COMBO_ITEMS = {"horizontal", "vertical", "both"}; public GravityProperty(@NotNull String name, @NotNull AttributeDefinition definition) { super(name, definition); myOptions.remove(getProperty("center_horizontal")); myOptions.remove(getProperty("center_vertical")); myOptions.set(getProperty("center"), new ComboOptionProperty(this, "center", CENTER) { @Override protected void setValue(RadViewComponent component, int index) throws Exception { if (index == 0) { setOptions(component, new String[]{"center_horizontal"}, new String[]{"center_vertical", "center"}); } else if (index == 1) { setOptions(component, new String[]{"center_vertical"}, new String[]{"center_horizontal", "center"}); } else { setOptions(component, new String[]{"center"}, new String[]{"center_horizontal", "center_vertical"}); } } }); myOptions.remove(getProperty("fill_horizontal")); myOptions.remove(getProperty("fill_vertical")); myOptions.set(getProperty("fill"), new ComboOptionProperty(this, "fill", FILL) { @Override protected void setValue(RadViewComponent component, int index) throws Exception { if (index == 0) { setOptions(component, new String[]{"fill_horizontal"}, new String[]{"fill_vertical", "fill"}); } else if (index == 1) { setOptions(component, new String[]{"fill_vertical"}, new String[]{"fill_horizontal", "fill"}); } else { setOptions(component, new String[]{"fill"}, new String[]{"fill_horizontal", "fill_vertical"}); } } }); int clip_vertical = getProperty("clip_vertical"); if (clip_vertical != -1) { myOptions.remove(clip_vertical); myOptions.set(getProperty("clip_horizontal"), new ComboOptionProperty(this, "clip", CLIP) { @Override protected void setValue(RadViewComponent component, int index) throws Exception { if (index == 0) { setOptions(component, new String[]{"clip_horizontal"}, new String[]{"clip_vertical"}); } else if (index == 1) { setOptions(component, new String[]{"clip_vertical"}, new String[]{"clip_horizontal"}); } else { setOptions(component, CLIP, null); } } }); } } private int getProperty(String name) { int size = myOptions.size(); for (int i = 0; i < size; i++) { if (name.equals(myOptions.get(i).getName())) { return i; } } return -1; } @Override public Object getValue(@NotNull RadViewComponent component) throws Exception { StringBuilder value = new StringBuilder("["); Set<String> options = getOptions(component); int index = 0; for (Property option : myOptions) { String name = null; if (option instanceof OptionProperty) { if (options.contains(((OptionProperty)option).getValueName())) { name = option.getName(); } } else { name = ((ComboOptionProperty)option).getValue(options); } if (name != null) { if (index++ > 0) { value.append(", "); } value.append(name); } } return value.append("]").toString(); } private void setOptions(final RadViewComponent component, @Nullable String[] setNames, @Nullable String[] unsetNames) throws Exception { final Set<String> options = new HashSet<String>(getOptions(component)); if (unsetNames != null) { for (String name : unsetNames) { options.remove(name); } } if (setNames != null) { Collections.addAll(options, setNames); } ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { if (options.isEmpty()) { XmlAttribute attribute = getAttribute(component); if (attribute != null) { attribute.delete(); } } else { component.getTag().setAttribute(myDefinition.getName(), getNamespace(component, true), StringUtil.join(options, "|")); } } }); } private abstract class ComboOptionProperty extends Property<RadViewComponent> { private final PropertyRenderer myRenderer = new LabelPropertyRenderer(null); private final PropertyEditor myEditor = new StringsComboEditor(COMBO_ITEMS); private final String[] myValues; public ComboOptionProperty(@Nullable Property parent, @NotNull String name, String[] values) { super(parent, name); myValues = values; } @Nullable public String getValue(Set<String> options) { StringBuilder values = new StringBuilder(); int index = 0; for (String value : myValues) { if (options.contains(value)) { if (index++ > 0) { values.append(", "); } values.append(value); } } return index == 0 ? null : values.toString(); } @Override public Object getValue(@NotNull RadViewComponent component) throws Exception { Set<String> options = getOptions(component); int lastIndex = -1; for (int i = 0; i < myValues.length; i++) { if (options.contains(myValues[i])) { lastIndex = i; } } return lastIndex == -1 ? null : COMBO_ITEMS[lastIndex]; } @Override public void setValue(@NotNull RadViewComponent component, Object value) throws Exception { int index = ArrayUtil.indexOf(COMBO_ITEMS, value); if (index == -1) { setOptions(component, null, myValues); } else { setValue(component, index); } } protected abstract void setValue(RadViewComponent component, int index) throws Exception; @Override public boolean isDefaultValue(@NotNull RadViewComponent component) throws Exception { Set<String> options = getOptions(component); for (String value : myValues) { if (options.contains(value)) { return false; } } return true; } @Override public void setDefaultValue(@NotNull RadViewComponent component) throws Exception { setValue(component, null); } @Override public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) { return null; } @NotNull @Override public PropertyRenderer getRenderer() { return myRenderer; } @Override public PropertyEditor getEditor() { return myEditor; } @Override public boolean needRefreshPropertyList() { return true; } } }