/* * Copyright 2003-2016 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 jetbrains.mps.nodeEditor.cells; import jetbrains.mps.openapi.editor.EditorContext; import jetbrains.mps.smodel.NodeReadAccessCasterInEditor; import jetbrains.mps.smodel.PropertySupport; import jetbrains.mps.smodel.SModelOperations; import jetbrains.mps.smodel.SNodeLegacy; import jetbrains.mps.util.Computable; import jetbrains.mps.util.annotation.Hack; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeAccessUtil; import org.jetbrains.mps.openapi.model.SNodeReference; import org.jetbrains.mps.openapi.module.SRepository; public class PropertyAccessor implements ModelAccessor { private SNode myNode; private String myPropertyName; private boolean myReadOnly; private boolean myAllowEmptyText; private final SNodeReference myPropertyDeclaration; private final SRepository myRepository; public PropertyAccessor(SNode node, String propertyName, boolean readOnly, boolean allowEmptyText, EditorContext editorContext) { myNode = node; myPropertyName = propertyName; myReadOnly = readOnly || SModelOperations.isReadOnly(node.getModel()) || editorContext.getEditorComponent().isReadOnly(); myAllowEmptyText = allowEmptyText; myPropertyDeclaration = NodeReadAccessCasterInEditor.runReadTransparentAction(new Computable<SNodeReference>() { @Override public SNodeReference compute() { SNode propertyDeclaration = new SNodeLegacy(myNode).getPropertyDeclaration(myPropertyName); return propertyDeclaration != null ? propertyDeclaration.getReference() : null; } }); myRepository = editorContext.getRepository(); } public SNode getNode() { return myNode; } protected SRepository getRepository() { return myRepository; } public String getPropertyName() { return myPropertyName; } @Override public String getText() { return fromInternal(doGetValue()); } @Override public void setText(String text) { if (!myReadOnly) { isValidText(text); if (text != null && text.length() == 0) { text = null; } if (isValidText_internal(text)) { doSetValue(toInternal(text)); } } } protected String doGetValue() { return NodeReadAccessCasterInEditor.runCleanPropertyAccessAction(new Computable<String>() { @Override public String compute() { if (myNode == null) { return null; } return SNodeAccessUtil.getProperty(myNode, myPropertyName); } }); } protected void doSetValue(String newText) { SNodeAccessUtil.setProperty(myNode, myPropertyName, newText); } @Override @Hack public boolean isValidText(String text) { return (isValidText_internal(text) && !isInvalidEmptyText(text)); } private boolean isValidText_internal(String text) { if (text != null && text.length() == 0) { text = null; } if (myReadOnly) { String propertyValue = getText(); return (text == null && (propertyValue == null || propertyValue.isEmpty())) || (text != null && text.equals(propertyValue)); } SNode node = getPropertyDeclaration(); if (node != null) { PropertySupport propertySupport = PropertySupport.getPropertySupport(node); return propertySupport.canSetValue(myNode, myPropertyName, text); } return true; } @Hack private boolean isInvalidEmptyText(String text) { return !myAllowEmptyText && (text == null || text.length() == 0); } private String fromInternal(String value) { SNode node = getPropertyDeclaration(); if (node != null) { PropertySupport propertySupport = PropertySupport.getPropertySupport(node); return propertySupport.fromInternalValue(value); } return value; } private String toInternal(String value) { SNode node = getPropertyDeclaration(); if (node != null) { PropertySupport propertySupport = PropertySupport.getPropertySupport(node); return propertySupport.toInternalValue(value); } return value; } private SNode getPropertyDeclaration() { return NodeReadAccessCasterInEditor.runReadTransparentAction(new Computable<SNode>() { @Override public SNode compute() { return myPropertyDeclaration != null ? myPropertyDeclaration.resolve(myRepository) : null; } }); } }