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

com.intellij.util.xml.ui.BaseControl Maven / Gradle / Ivy

Go to download

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

The newest version!
/*
 * Copyright 2000-2014 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.util.xml.ui;

import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.EventDispatcher;
import com.intellij.util.xml.DomElement;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.lang.reflect.InvocationTargetException;

/**
 * @author peter
 */
public abstract class BaseControl extends DomUIControl implements Highlightable {
  public static final Color ERROR_BACKGROUND = new Color(255,204,204);
  public static final Color ERROR_FOREGROUND = SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor();
  public static final Color WARNING_BACKGROUND = new Color(255,255,204);

  private final EventDispatcher myDispatcher = EventDispatcher.create(CommitListener.class);

  private Bound myBoundComponent;
  private final DomWrapper myDomWrapper;
  private boolean myCommitting;

  private Color myDefaultForeground;
  private Color myDefaultBackground;

  protected BaseControl(final DomWrapper domWrapper) {
    myDomWrapper = domWrapper;
  }

  private void checkInitialized() {
    if (myBoundComponent != null) return;

    initialize(null);
  }

  protected JComponent getHighlightedComponent(Bound component) {
    return component;
  }

  protected final Color getDefaultBackground() {
    return myDefaultBackground;
  }

  protected final Color getDefaultForeground() {
    return myDefaultForeground;
  }

  protected final Color getErrorBackground() {
    return ERROR_BACKGROUND;
  }

  protected final Color getWarningBackground() {
    return WARNING_BACKGROUND;
  }

  protected final Color getErrorForeground() {
    return ERROR_FOREGROUND;
  }


  private void initialize(final Bound boundComponent) {
    myBoundComponent = createMainComponent(boundComponent);
    final JComponent highlightedComponent = getHighlightedComponent(myBoundComponent);
    myDefaultForeground = highlightedComponent.getForeground();
    myDefaultBackground = highlightedComponent.getBackground();
    final JComponent component = getComponentToListenFocusLost(myBoundComponent);
    if (component != null) {
      component.addFocusListener(new FocusListener() {
        @Override
        public void focusGained(FocusEvent e) {
        }

        @Override
        public void focusLost(FocusEvent e) {
          if (!e.isTemporary() && isValid()) {
            commit();
          }
        }
      });
    }

    updateComponent();
  }

  @Nullable
  protected JComponent getComponentToListenFocusLost(Bound component) {
    return null;
  }

  protected abstract Bound createMainComponent(Bound boundedComponent);

  @Override
  public void bind(JComponent component) {
    initialize((Bound)component);
  }

  @Override
  public void addCommitListener(CommitListener listener) {
    myDispatcher.addListener(listener);
  }

  @Override
  public void removeCommitListener(CommitListener listener) {
    myDispatcher.removeListener(listener);
  }

  @Override
  public final DomElement getDomElement() {
    return myDomWrapper.getWrappedElement();
  }

  public final DomWrapper getDomWrapper() {
    return myDomWrapper;
  }

  @Override
  public final Bound getComponent() {
    checkInitialized();
    return myBoundComponent;
  }

  @Override
  public void dispose() {
  }

  @Override
  public final void commit() {
    if (isValid() && !isCommitted()) {
      setValueToXml(getValue());
      updateComponent();
    }
  }

  protected final boolean isValid() {
    return myDomWrapper.isValid();
  }

  private static boolean valuesAreEqual(final Object valueInXml, final Object valueInControl) {
    return "".equals(valueInControl) && null == valueInXml ||
           equalModuloTrim(valueInXml, valueInControl) ||
           Comparing.equal(valueInXml, valueInControl);
  }

  private static boolean equalModuloTrim(final Object valueInXml, final Object valueInControl) {
    return valueInXml instanceof String && valueInControl instanceof String && ((String)valueInXml).trim().equals(((String)valueInControl).trim());
  }

  @Override
  public final void reset() {
    if (!myCommitting) {
      doReset();
      updateComponent();
    }
  }

  @Override
  public void updateHighlighting() {
    updateComponent();
  }

  protected void updateComponent() {
  }

  protected void doReset() {
    if (valuesDiffer()) {
      setValue(getValueFromXml());
    }
  }

  protected boolean isCommitted() {
    return !valuesDiffer();
  }

  private boolean valuesDiffer() {
    return !valuesAreEqual(getValueFromXml(), getValue());
  }

  private void setValueToXml(final T value) {
    if (myCommitting) return;
    myCommitting = true;
    try {
      final CommitListener multicaster = myDispatcher.getMulticaster();
      multicaster.beforeCommit(this);
      new WriteCommandAction(getProject(), getDomWrapper().getFile()) {
        @Override
        protected void run(Result result) throws Throwable {
          doCommit(value);
        }
      }.execute();
      multicaster.afterCommit(this);
    }
    finally {
      myCommitting = false;
    }
  }

  protected void doCommit(final T value) throws IllegalAccessException, InvocationTargetException {
    myDomWrapper.setValue("".equals(value) ? null : value);
  }

  protected final Project getProject() {
    return myDomWrapper.getProject();
  }

  private T getValueFromXml() {
    try {
      return myDomWrapper.getValue();
    }
    catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
    catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
  }


  @Override
  public boolean canNavigate(DomElement element) {
    return false;
  }

  @Override
  public void navigate(DomElement element) {
  }

  @Nullable
  protected abstract T getValue();
  protected abstract void setValue(T value);

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy