/**
   * Asks current editor to refresh its state in accordance with the arrangement rule shown at the
   * given row.
   *
   * @param row row index of the rule which match condition should be edited (if defined); <code>
   *     '-1'</code> as an indication that no settings should be active
   */
  public void reset(int row) {
    // Reset state.
    myRow = row;
    myFocusRequestor = myDefaultFocusRequestor;
    mySkipStateChange = true;
    try {
      for (ArrangementUiComponent component : myComponents.values()) {
        component.reset();
      }
    } finally {
      mySkipStateChange = false;
    }

    ArrangementMatchingRulesModel model = myControl.getModel();
    if (row < 0 || row >= model.getSize()) {
      myRow = -1;
      return;
    }

    Object element = model.getElementAt(row);
    ArrangementSettingsToken orderType =
        element instanceof ArrangementMatchRule
            ? ((ArrangementMatchRule) element).getOrderType()
            : null;
    final ArrangementMatchCondition condition;
    final Map<ArrangementSettingsToken, Object> conditionTokens;

    if (element instanceof EmptyArrangementRuleComponent) {
      // We need to disable conditions which are not applicable for empty rules (e.g. we don't want
      // to enable 'volatile' condition
      // for java rearranger if no 'field' condition is selected.
      condition = null;
      conditionTokens = ContainerUtilRt.newHashMap();
    } else if (!(element instanceof StdArrangementMatchRule)) {
      return;
    } else {
      condition = ((StdArrangementMatchRule) element).getMatcher().getCondition();
      conditionTokens = ArrangementUtil.extractTokens(condition);
    }

    mySkipStateChange = true;
    try {
      for (ArrangementUiComponent component : myComponents.values()) {
        ArrangementSettingsToken token = component.getToken();
        if (token != null
            && (token.equals(orderType) || mySettingsManager.isEnabled(token, condition))) {
          component.setEnabled(true);
          component.setSelected(conditionTokens.containsKey(token));
          Object value = conditionTokens.get(token);
          if (value != null) {
            component.setData(value);
          }
        }
      }

      refreshConditions();
    } finally {
      mySkipStateChange = false;
    }
  }
  private void addCondition(@NotNull ArrangementUiComponent component) {
    mySkipStateChange = true;
    try {
      component.setSelected(true);
      Collection<Set<ArrangementSettingsToken>> mutexes = mySettingsManager.getMutexes();

      // Update 'mutex conditions', i.e. conditions which can't be active at the same time (e.g.
      // type 'field' and type 'method').
      for (Set<ArrangementSettingsToken> mutex : mutexes) {
        if (!mutex.contains(component.getToken())) {
          continue;
        }
        for (ArrangementSettingsToken key : mutex) {
          if (key.equals(component.getToken())) {
            continue;
          }
          ArrangementUiComponent c = myComponents.get(key);
          if (c != null && c.isEnabled()) {
            removeCondition(c);
          }
        }
      }
      refreshConditions();
    } finally {
      mySkipStateChange = false;
    }
  }
 /**
  * Disable conditions not applicable at the current context (e.g. disable 'synchronized' if no
  * 'method' is selected).
  */
 private void refreshConditions() {
   Pair<ArrangementMatchCondition, ArrangementSettingsToken> pair = buildCondition();
   ArrangementMatchCondition condition = pair == null ? null : pair.first;
   for (ArrangementUiComponent component : myComponents.values()) {
     ArrangementSettingsToken token = component.getToken();
     if (token == null) {
       continue;
     }
     boolean enabled = mySettingsManager.isEnabled(token, condition);
     component.setEnabled(enabled);
     if (!enabled) {
       component.setSelected(false);
     }
   }
 }
  private void onMouseClicked(@NotNull MouseEvent e) {
    if (myRow < 0) {
      return;
    }

    Point locationOnScreen = e.getLocationOnScreen();
    for (ArrangementUiComponent component : myComponents.values()) {
      Rectangle screenBounds = component.getScreenBounds();
      if (screenBounds == null || !screenBounds.contains(locationOnScreen)) {
        continue;
      }
      if (component.isEnabled()) {
        if (component.isSelected()) {
          removeCondition(component);
        } else {
          addCondition(component);
        }
      }
      apply();
      return;
    }
  }
 @Nullable
 private Pair<ArrangementMatchCondition, ArrangementSettingsToken> buildCondition() {
   List<ArrangementMatchCondition> conditions = ContainerUtilRt.newArrayList();
   ArrangementSettingsToken orderType = null;
   for (ArrangementUiComponent component : myComponents.values()) {
     if (!component.isEnabled() || !component.isSelected()) {
       continue;
     }
     ArrangementSettingsToken token = component.getToken();
     if (token != null && StdArrangementTokens.Order.is(token)) {
       orderType = token;
     } else {
       conditions.add(component.getMatchCondition());
     }
   }
   if (orderType != null && !conditions.isEmpty()) {
     return Pair.create(
         ArrangementUtil.combine(
             conditions.toArray(new ArrangementMatchCondition[conditions.size()])),
         orderType);
   } else {
     return null;
   }
 }
  private void addToken(@NotNull CompositeArrangementSettingsToken rowToken) {
    List<CompositeArrangementSettingsToken> tokens = ArrangementUtil.flatten(rowToken);
    GridBag labelConstraints =
        new GridBag()
            .anchor(GridBagConstraints.NORTHWEST)
            .insets(ArrangementConstants.VERTICAL_PADDING, 0, 0, 0);
    MultiRowFlowPanel panel =
        new MultiRowFlowPanel(
            FlowLayout.LEFT,
            ArrangementConstants.HORIZONTAL_GAP,
            ArrangementConstants.VERTICAL_GAP);
    List<ArrangementSettingsToken> prevTokens = ContainerUtilRt.newArrayList();
    StdArrangementTokenUiRole prevRole = null;
    ArrangementUiComponent component;
    JComponent uiComponent;
    for (CompositeArrangementSettingsToken token : tokens) {
      StdArrangementTokenUiRole role = token.getRole();
      if (role != prevRole && !prevTokens.isEmpty()) {
        component =
            ArrangementUtil.buildUiComponent(role, prevTokens, myColorsProvider, mySettingsManager);
        component.setListener(this);
        for (ArrangementSettingsToken prevToken : prevTokens) {
          myComponents.put(prevToken, component);
        }
        panel.add(component.getUiComponent());
        panel = addRowIfNecessary(panel);
        prevRole = null;
        prevTokens.clear();
      }
      component =
          ArrangementUtil.buildUiComponent(
              role,
              Collections.singletonList(token.getToken()),
              myColorsProvider,
              mySettingsManager);
      component.setListener(this);
      uiComponent = component.getUiComponent();
      switch (role) {
        case LABEL:
          panel = addRowIfNecessary(panel);
          add(uiComponent, labelConstraints);
          myLabelWidth = Math.max(myLabelWidth, uiComponent.getPreferredSize().width);
          prevRole = null;
          break;
        case TEXT_FIELD:
          panel = addRowIfNecessary(panel);

          ArrangementUiComponent textLabel =
              ArrangementUtil.buildUiComponent(
                  StdArrangementTokenUiRole.LABEL,
                  Collections.singletonList(token.getToken()),
                  myColorsProvider,
                  mySettingsManager);
          JComponent textLabelComponent = textLabel.getUiComponent();
          add(textLabelComponent, labelConstraints);
          myLabelWidth = Math.max(myLabelWidth, textLabelComponent.getPreferredSize().width);

          panel.add(uiComponent);
          panel = addRowIfNecessary(panel);
          prevRole = null;

          myComponents.put(token.getToken(), component);

          if (myDefaultFocusRequestor == null) {
            myDefaultFocusRequestor = uiComponent;
          }
          break;
        default:
          if (role == StdArrangementTokenUiRole.COMBO_BOX) {
            prevTokens.add(token.getToken());
            prevRole = role;
            break;
          }

          panel.add(uiComponent);
          myComponents.put(token.getToken(), component);
      }
    }

    if (prevRole != null && !prevTokens.isEmpty()) {
      component =
          ArrangementUtil.buildUiComponent(
              prevRole, prevTokens, myColorsProvider, mySettingsManager);
      panel.add(component.getUiComponent());
      component.setListener(this);
      for (ArrangementSettingsToken prevToken : prevTokens) {
        myComponents.put(prevToken, component);
      }
    }
    addRowIfNecessary(panel);
  }