All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.uiDesigner.propertyInspector.properties.IntroStringProperty Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition ui-designer library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2009 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.uiDesigner.propertyInspector.properties;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.uiDesigner.*;
import com.intellij.uiDesigner.core.SupportCode;
import com.intellij.uiDesigner.lw.IProperty;
import com.intellij.uiDesigner.lw.StringDescriptor;
import com.intellij.uiDesigner.propertyInspector.IntrospectedProperty;
import com.intellij.uiDesigner.propertyInspector.PropertyEditor;
import com.intellij.uiDesigner.propertyInspector.PropertyRenderer;
import com.intellij.uiDesigner.propertyInspector.editors.string.StringEditor;
import com.intellij.uiDesigner.propertyInspector.renderers.StringRenderer;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.radComponents.RadRootContainer;
import com.intellij.uiDesigner.snapShooter.SnapshotContext;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.lang.reflect.Method;
import java.util.Locale;

/**
 * @author Anton Katilin
 * @author Vladimir Kondratyev
 */
public final class IntroStringProperty extends IntrospectedProperty {
  private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.propertyInspector.IntroStringProperty");

  /**
   * value: HashMap
   */
  @NonNls
  private static final String CLIENT_PROP_NAME_2_DESCRIPTOR = "name2descriptor";

  private final StringRenderer myRenderer;
  private StringEditor myEditor;
  private final Project myProject;

  public IntroStringProperty(final String name,
                             final Method readMethod,
                             final Method writeMethod,
                             final Project project,
                             final boolean storeAsClient) {
    super(name, readMethod, writeMethod, storeAsClient);
    myProject = project;
    myRenderer = new StringRenderer();
  }

  @NotNull
  public PropertyRenderer getRenderer() {
    return myRenderer;
  }

  public PropertyEditor getEditor() {
    if (myEditor == null) {
      myEditor = new StringEditor(myProject, this);
    }
    return myEditor;
  }

  /**
   * @return per RadComponent map between string property name and its StringDescriptor value.
   */
  @NotNull
  private static HashMap getName2Descriptor(final RadComponent component){
    //noinspection unchecked
    HashMap name2Descriptor = (HashMap)component.getClientProperty(CLIENT_PROP_NAME_2_DESCRIPTOR);
    if(name2Descriptor == null){
      name2Descriptor = new HashMap();
      component.putClientProperty(CLIENT_PROP_NAME_2_DESCRIPTOR, name2Descriptor);
    }
    return name2Descriptor;
  }

  /**
   * Utility method which merge together text and mnemonic at some position
   */
  private static String mergeTextAndMnemonic(String text, final int mnemonic, final int mnemonicIndex){
    if (text == null) {
      text = "";
    }
    final int index;
    if(
      mnemonicIndex >= 0 &&
      mnemonicIndex < text.length() &&
      Character.toUpperCase(text.charAt(mnemonicIndex)) == mnemonic
    ){
      // Index really corresponds to the mnemonic
      index = mnemonicIndex;
    }
    else{
      // Mnemonic exists but index is wrong
      index = -1;
    }

    final StringBuffer buffer = new StringBuffer(text);
    if(index != -1){
      buffer.insert(index, '&');
      // Quote all '&' except inserted one
      for(int i = buffer.length() - 1; i >= 0; i--){
        if(buffer.charAt(i) == '&' && i != index){
          buffer.insert(i, '&');
        }
      }
    }
    return buffer.toString();
  }

  /**
   * It's good that method is overriden here.
   *
   * @return instance of {@link StringDescriptor}
   */
  public StringDescriptor getValue(final RadComponent component) {
    // 1. resource bundle
    {
      final StringDescriptor descriptor = getName2Descriptor(component).get(getName());
      if(descriptor != null){
        return descriptor;
      }
    }

    // 2. plain value
    final JComponent delegee = component.getDelegee();
    return stringDescriptorFromValue(component, delegee);
  }

  private StringDescriptor stringDescriptorFromValue(final RadComponent component, final JComponent delegee) {
    final StringDescriptor result;
    if(SwingProperties.TEXT.equals(getName()) && (delegee instanceof JLabel)){
      final JLabel label = (JLabel)delegee;
      result = StringDescriptor.create(
        mergeTextAndMnemonic(label.getText(), label.getDisplayedMnemonic(), label.getDisplayedMnemonicIndex())
      );
    }
    else
    if(SwingProperties.TEXT.equals(getName()) && (delegee instanceof AbstractButton)){
      final AbstractButton button = (AbstractButton)delegee;
      result = StringDescriptor.create(
        mergeTextAndMnemonic(button.getText(), button.getMnemonic(), button.getDisplayedMnemonicIndex())
      );
    }
    else {
      if (component != null) {
        result = StringDescriptor.create((String) invokeGetter(component));
      }
      else {
        try {
          result = StringDescriptor.create((String) myReadMethod.invoke(delegee, EMPTY_OBJECT_ARRAY));
        }
        catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    }

    if (result != null) {
      // in this branch, the StringDescriptor is always a plain string, so resolve() is not necessary
      result.setResolvedValue(result.getValue());
    }
    return result;
  }

  protected void setValueImpl(final RadComponent component, final StringDescriptor value) throws Exception {
    // 1. Put value into map
    if(value == null || (value.getBundleName() == null && !value.isNoI18n())) {
      getName2Descriptor(component).remove(getName());
    }
    else{
      getName2Descriptor(component).put(getName(), value);
    }

    // 2. Apply real string value to JComponent peer
    final JComponent delegee = component.getDelegee();

    Locale locale = (Locale)component.getClientProperty(RadComponent.CLIENT_PROP_LOAD_TIME_LOCALE);
    if (locale == null) {
      RadRootContainer root = (RadRootContainer) FormEditingUtil.getRoot(component);
      if (root != null) {
        locale = root.getStringDescriptorLocale();
      }
    }
    final String resolvedValue = (value != null && value.getValue() != null)
                                 ? value.getValue()
                                 : StringDescriptorManager.getInstance(component.getModule()).resolve(value, locale);

    if (value != null) {
      value.setResolvedValue(resolvedValue);
    }

    if(SwingProperties.TEXT.equals(getName())) {
      final SupportCode.TextWithMnemonic textWithMnemonic = SupportCode.parseText(resolvedValue);
      if (delegee instanceof JLabel) {
        final JLabel label = (JLabel)delegee;
        label.setText(textWithMnemonic.myText);
        if(textWithMnemonic.myMnemonicIndex != -1){
          label.setDisplayedMnemonic(textWithMnemonic.getMnemonicChar());
          label.setDisplayedMnemonicIndex(textWithMnemonic.myMnemonicIndex);
        }
        else{
          label.setDisplayedMnemonic(0);
        }
      }
      else if (delegee instanceof AbstractButton) {
        final AbstractButton button = (AbstractButton)delegee;
        button.setText(textWithMnemonic.myText);
        if(textWithMnemonic.myMnemonicIndex != -1){
          button.setMnemonic(textWithMnemonic.getMnemonicChar());
          button.setDisplayedMnemonicIndex(textWithMnemonic.myMnemonicIndex);
        }
        else{
          button.setMnemonic(0);
        }
      }
      else {
        invokeSetter(component, resolvedValue);
      }
      checkUpdateBindingFromText(component, value, textWithMnemonic);
    }
    else{
      invokeSetter(component, resolvedValue);
    }
  }

  private static void checkUpdateBindingFromText(final RadComponent component, final StringDescriptor value, final SupportCode.TextWithMnemonic textWithMnemonic) {
    if (component.isLoadingProperties()) {
      return;
    }
    // only generate binding from text if default locale is active (IDEADEV-9427)
    if (value.getValue() == null) {
      RadRootContainer root = (RadRootContainer) FormEditingUtil.getRoot(component);
      Locale locale = root.getStringDescriptorLocale();
      if (locale != null && locale.getDisplayName().length() > 0) {
        return;
      }
    }

    BindingProperty.checkCreateBindingFromText(component, textWithMnemonic.myText);
    if (component.getDelegee() instanceof JLabel) {
      for(IProperty prop: component.getModifiedProperties()) {
        if (prop.getName().equals(SwingProperties.LABEL_FOR) && prop instanceof IntroComponentProperty) {
          ((IntroComponentProperty) prop).updateLabelForBinding(component);
        }
      }
    }
  }

  public boolean refreshValue(RadComponent component) {
    StringDescriptor descriptor = getValue(component);
    if (descriptor.getValue() != null) return false;
    String oldResolvedValue = descriptor.getResolvedValue();
    descriptor.setResolvedValue(null);
    try {
      setValueImpl(component, descriptor);
      return !Comparing.equal(oldResolvedValue, descriptor.getResolvedValue());
    }
    catch (Exception e) {
      LOG.error(e);
      return false;
    }
  }

  public void write(@NotNull final StringDescriptor value, final XmlWriter writer) {
    writer.writeStringDescriptor(value,
                                 UIFormXmlConstants.ATTRIBUTE_VALUE,
                                 UIFormXmlConstants.ATTRIBUTE_RESOURCE_BUNDLE,
                                 UIFormXmlConstants.ATTRIBUTE_KEY);
  }

  @Override public void importSnapshotValue(final SnapshotContext context, final JComponent component, final RadComponent radComponent) {
    try {
      Object value = myReadMethod.invoke(component, EMPTY_OBJECT_ARRAY);
      if (value != null) {
        setValue(radComponent, stringDescriptorFromValue(null, component));
      }
    }
    catch (Exception e) {
      // ignore
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy