Package com.google.gdt.eclipse.designer.model.property.css

Source Code of com.google.gdt.eclipse.designer.model.property.css.RuleAccessor$RuleDesc

/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* 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.google.gdt.eclipse.designer.model.property.css;

import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gdt.eclipse.designer.model.widgets.support.GwtState;
import com.google.gdt.eclipse.designer.model.widgets.support.IGwtStateProvider;

import org.eclipse.wb.core.model.ObjectInfo;
import org.eclipse.wb.core.model.broadcast.ObjectEventListener;
import org.eclipse.wb.internal.css.model.CssRuleNode;
import org.eclipse.wb.internal.css.parser.CssEditContext;
import org.eclipse.wb.internal.css.semantics.Semantics;

import org.apache.commons.lang.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Accessor for {@link Semantics} by style names.
*
* @author scheglov_ke
* @coverage gwt.model.property
*/
public class RuleAccessor {
  private final ObjectInfo m_object;
  private final GwtState m_gwtState;
  private final Set<ContextDescription> m_updatedContexts = Sets.newHashSet();
  private final Map<CssRuleNode, Semantics> m_semantics = new MapMaker().weakKeys().makeMap();
  ////////////////////////////////////////////////////////////////////////////
  //
  // Instance access
  //
  ////////////////////////////////////////////////////////////////////////////
  private static final Map<ObjectInfo, RuleAccessor> m_instances = Maps.newHashMap();

  /**
   * @return the {@link RuleAccessor} for this hierarchy.
   */
  public static RuleAccessor get(ObjectInfo object) {
    final ObjectInfo rootObject = object.getRoot();
    RuleAccessor accessor = m_instances.get(rootObject);
    if (accessor == null) {
      accessor = new RuleAccessor(rootObject);
      m_instances.put(rootObject, accessor);
      rootObject.addBroadcastListener(new ObjectEventListener() {
        @Override
        public void dispose() throws Exception {
          m_instances.remove(rootObject);
        }

        @Override
        public void endEdit_aboutToRefresh() throws Exception {
          RuleAccessor accessor = m_instances.get(rootObject);
          accessor.commit();
        }
      });
      new FileContextDescriptionSupport(rootObject);
    }
    return accessor;
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // Constructor
  //
  ////////////////////////////////////////////////////////////////////////////
  public RuleAccessor(ObjectInfo object) {
    m_object = object;
    m_gwtState = ((IGwtStateProvider) object).getState();
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  // Access
  //
  ////////////////////////////////////////////////////////////////////////////
  /**
   * @return the root {@link ObjectInfo} of hierarchy.
   */
  public ObjectInfo getObject() {
    return m_object;
  }

  /**
   * @return all {@link ContextDescription}s which are used for this hierarchy.
   */
  public List<ContextDescription> getContexts() throws Exception {
    List<ContextDescription> contexts = Lists.newArrayList();
    m_object.getBroadcast(StylePropertyEditorListener.class).addContextDescriptions(
        m_object,
        contexts);
    return contexts;
  }

  /**
   * It is possible, that user expanded "style" property, but then switched to CSS file and removed
   * rule. Then he switches back to Design page, we notice that CSS file was changed and refresh
   * design canvas, including replacing properties. However just before this we try to paint
   * existing properties as is, and fail because of not existing {@link Semantics}.
   *
   * @return <code>true</code> if {@link #getSemantics(String)} will return actual {@link Semantics}
   *         bound to some rule.
   */
  public boolean hasSemantics(String styleName) throws Exception {
    return getRule(styleName) != null;
  }

  /**
   * @return the {@link Semantics} for modifying CSS rule for given style name, may be
   *         <code>null</code>.
   */
  public Semantics getSemantics(String styleName) throws Exception {
    RuleDesc ruleDesc = getRule(styleName);
    // if no rule, use empty Semantics, to avoid null checks in many places
    if (ruleDesc == null) {
      return new Semantics();
    }
    // create Semantics for rule
    CssRuleNode rule = ruleDesc.rule;
    Semantics semantics = m_semantics.get(rule);
    if (semantics == null) {
      semantics = new Semantics();
      semantics.parse(rule);
      m_semantics.put(rule, semantics);
    }
    return semantics;
  }

  /**
   * Applies the {@link Semantics} into the source file.
   */
  public void applySemantics(String styleName) throws Exception {
    RuleDesc ruleDesc = getRule(styleName);
    Semantics semantics = getSemantics(styleName);
    semantics.update(ruleDesc.rule);
    m_updatedContexts.add(ruleDesc.contextDescription);
  }

  /**
   * Commits changes into underlying file.
   */
  private void commit() throws Exception {
    for (ContextDescription context : m_updatedContexts) {
      context.commit();
    }
    m_updatedContexts.clear();
    m_gwtState.isModified();
  }

  /**
   * @return the {@link RuleDesc} of given style name, may be <code>null</code>.
   */
  private RuleDesc getRule(String styleName) throws Exception {
    for (ContextDescription contextDescription : getContexts()) {
      for (CssRuleNode ruleNode : contextDescription.getRules()) {
        if (StringUtils.equals(contextDescription.getStyleName(ruleNode), styleName)) {
          RuleDesc ruleDesc = new RuleDesc();
          ruleDesc.contextDescription = contextDescription;
          ruleDesc.rule = ruleNode;
          return ruleDesc;
        }
      }
    }
    return null;
  }

  /**
   * Structure with {@link CssEditContext} and {@link CssRuleNode} from it.
   */
  private static class RuleDesc {
    ContextDescription contextDescription;
    CssRuleNode rule;
  }
}
TOP

Related Classes of com.google.gdt.eclipse.designer.model.property.css.RuleAccessor$RuleDesc

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.