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

com.intellij.uiDesigner.FormEditingUtil 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-2013 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;

import com.intellij.lang.properties.PropertiesReferenceManager;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.uiDesigner.compiler.AsmCodeGenerator;
import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.designSurface.ComponentDropLocation;
import com.intellij.uiDesigner.designSurface.DraggedComponentList;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.designSurface.Painter;
import com.intellij.uiDesigner.editor.UIFormEditor;
import com.intellij.uiDesigner.lw.*;
import com.intellij.uiDesigner.palette.ComponentItem;
import com.intellij.uiDesigner.palette.Palette;
import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager;
import com.intellij.uiDesigner.propertyInspector.properties.BindingProperty;
import com.intellij.uiDesigner.propertyInspector.properties.IntroComponentProperty;
import com.intellij.uiDesigner.radComponents.RadAbstractGridLayoutManager;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.radComponents.RadContainer;
import com.intellij.uiDesigner.radComponents.RadRootContainer;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;

/**
 * @author Anton Katilin
 * @author Vladimir Kondratyev
 */
public final class FormEditingUtil {
  private FormEditingUtil() {
  }

  public static boolean canDeleteSelection(final GuiEditor editor) {
    final ArrayList selection = getSelectedComponents(editor);
    if (selection.isEmpty()) return false;
    final RadRootContainer rootContainer = editor.getRootContainer();
    if (rootContainer.getComponentCount() > 0 && selection.contains(rootContainer.getComponent(0))) {
      return false;
    }
    return true;
  }

  /**
   * This method must be executed in command
   *
   * @param editor the editor in which the selection is deleted.
   */
  public static void deleteSelection(final GuiEditor editor) {
    final List selection = getSelectedComponents(editor);
    deleteComponents(selection, true);
    editor.refreshAndSave(true);
  }

  public static void deleteComponents(final Collection selection, boolean deleteEmptyCells) {
    if (selection.size() == 0) {
      return;
    }
    final RadRootContainer rootContainer = (RadRootContainer)getRoot(selection.iterator().next());
    final Set deletedComponentIds = new HashSet();
    for (final RadComponent component : selection) {
      boolean wasSelected = component.isSelected();
      final RadContainer parent = component.getParent();

      boolean wasPackedHorz = false;
      boolean wasPackedVert = false;
      if (parent.getParent() != null && parent.getParent().isXY()) {
        final Dimension minSize = parent.getMinimumSize();
        wasPackedHorz = parent.getWidth() == minSize.width;
        wasPackedVert = parent.getHeight() == minSize.height;
      }

      iterate(component, new ComponentVisitor() {
        public boolean visit(final IComponent c) {
          RadComponent rc = (RadComponent)c;
          BindingProperty.checkRemoveUnusedField(rootContainer, rc.getBinding(), null);
          deletedComponentIds.add(rc.getId());
          return true;
        }
      });


      GridConstraints delConstraints = parent.getLayoutManager().isGrid() ? component.getConstraints() : null;

      int index = parent.indexOfComponent(component);
      parent.removeComponent(component);
      if (wasSelected) {
        if (parent.getComponentCount() > index) {
          parent.getComponent(index).setSelected(true);
        }
        else if (index > 0 && parent.getComponentCount() == index) {
          parent.getComponent(index - 1).setSelected(true);
        }
        else {
          parent.setSelected(true);
        }
      }
      if (delConstraints != null && deleteEmptyCells) {
        deleteEmptyGridCells(parent, delConstraints);
      }

      if (wasPackedHorz || wasPackedVert) {
        final Dimension minSize = parent.getMinimumSize();
        Dimension newSize = new Dimension(parent.getWidth(), parent.getHeight());
        if (wasPackedHorz) {
          newSize.width = minSize.width;
        }
        if (wasPackedVert) {
          newSize.height = minSize.height;
        }
        parent.setSize(newSize);
      }
    }

    iterate(rootContainer, new ComponentVisitor() {
      public boolean visit(final IComponent component) {
        RadComponent rc = (RadComponent)component;
        for (IProperty p : component.getModifiedProperties()) {
          if (p instanceof IntroComponentProperty) {
            IntroComponentProperty icp = (IntroComponentProperty)p;
            final String value = icp.getValue(rc);
            if (deletedComponentIds.contains(value)) {
              try {
                icp.resetValue(rc);
              }
              catch (Exception e) {
                // ignore
              }
            }
          }
        }
        return true;
      }
    });
  }

  public static void deleteEmptyGridCells(final RadContainer parent, final GridConstraints delConstraints) {
    deleteEmptyGridCells(parent, delConstraints, true);
    deleteEmptyGridCells(parent, delConstraints, false);
  }

  private static void deleteEmptyGridCells(final RadContainer parent, final GridConstraints delConstraints, final boolean isRow) {
    final RadAbstractGridLayoutManager layoutManager = parent.getGridLayoutManager();
    for (int cell = delConstraints.getCell(isRow) + delConstraints.getSpan(isRow) - 1; cell >= delConstraints.getCell(isRow); cell--) {
      if (cell < parent.getGridCellCount(isRow) && GridChangeUtil.canDeleteCell(parent, cell, isRow) == GridChangeUtil.CellStatus.Empty &&
          !layoutManager.isGapCell(parent, isRow, cell)) {
        layoutManager.deleteGridCells(parent, cell, isRow);
      }
    }
  }

  public static final int EMPTY_COMPONENT_SIZE = 5;

  private static Component getDeepestEmptyComponentAt(JComponent parent, Point location) {
    int size = parent.getComponentCount();

    for (int i = 0; i < size; i++) {
      Component child = parent.getComponent(i);

      if (child.isShowing()) {
        if (child.getWidth() < EMPTY_COMPONENT_SIZE || child.getHeight() < EMPTY_COMPONENT_SIZE) {
          Point childLocation = child.getLocationOnScreen();
          Rectangle bounds = new Rectangle();

          bounds.x = childLocation.x;
          bounds.y = childLocation.y;
          bounds.width = child.getWidth();
          bounds.height = child.getHeight();
          bounds.grow(child.getWidth() < EMPTY_COMPONENT_SIZE ? EMPTY_COMPONENT_SIZE : 0,
                      child.getHeight() < EMPTY_COMPONENT_SIZE ? EMPTY_COMPONENT_SIZE : 0);

          if (bounds.contains(location)) {
            return child;
          }
        }

        if (child instanceof JComponent) {
          Component result = getDeepestEmptyComponentAt((JComponent)child, location);

          if (result != null) {
            return result;
          }
        }
      }
    }

    return null;
  }

  /**
   * @param x in editor pane coordinates
   * @param y in editor pane coordinates
   */
  public static RadComponent getRadComponentAt(final RadRootContainer rootContainer, final int x, final int y) {
    Point location = new Point(x, y);
    SwingUtilities.convertPointToScreen(location, rootContainer.getDelegee());
    Component c = getDeepestEmptyComponentAt(rootContainer.getDelegee(), location);

    if (c == null) {
      c = SwingUtilities.getDeepestComponentAt(rootContainer.getDelegee(), x, y);
    }

    RadComponent result = null;

    while (c != null) {
      if (c instanceof JComponent) {
        final RadComponent component = (RadComponent)((JComponent)c).getClientProperty(RadComponent.CLIENT_PROP_RAD_COMPONENT);
        if (component != null) {

          if (result == null) {
            result = component;
          }
          else {
            final Point p = SwingUtilities.convertPoint(rootContainer.getDelegee(), x, y, c);
            if (Painter.getResizeMask(component, p.x, p.y) != 0) {
              result = component;
            }
          }
        }
      }
      c = c.getParent();
    }

    return result;
  }

  /**
   * @return component which has dragger. There is only one component with the dargger
   *         at a time.
   */
  @Nullable
  public static RadComponent getDraggerHost(@NotNull final GuiEditor editor) {
    final Ref result = new Ref();
    iterate(
      editor.getRootContainer(),
      new ComponentVisitor() {
        public boolean visit(final RadComponent component) {
          if (component.hasDragger()) {
            result.set(component);
            return false;
          }
          return true;
        }
      }
    );

    return result.get();
  }


  public static Cursor getMoveDropCursor() {
    try {
      return Cursor.getSystemCustomCursor("MoveDrop.32x32");
    }
    catch (Exception ex) {
      return Cursor.getDefaultCursor();
    }
  }

  public static Cursor getMoveNoDropCursor() {
    try {
      return Cursor.getSystemCustomCursor("MoveNoDrop.32x32");
    }
    catch (Exception ex) {
      return Cursor.getDefaultCursor();
    }
  }

  public static Cursor getCopyDropCursor() {
    try {
      return Cursor.getSystemCustomCursor("CopyDrop.32x32");
    }
    catch (Exception ex) {
      return Cursor.getDefaultCursor();
    }
  }

  /**
   * @return currently selected components. Method returns the minimal amount of
   *         selected component which contains all selected components. It means that if the
   *         selected container contains some selected children then only this container
   *         will be added to the returned array.
   */
  @NotNull
  public static ArrayList getSelectedComponents(@NotNull final GuiEditor editor) {
    final ArrayList result = new ArrayList();
    calcSelectedComponentsImpl(result, editor.getRootContainer());
    return result;
  }

  private static void calcSelectedComponentsImpl(final ArrayList result, final RadContainer container) {
    if (container.isSelected()) {
      if (container.getParent() != null) { // ignore RadRootContainer
        result.add(container);
        return;
      }
    }

    for (int i = 0; i < container.getComponentCount(); i++) {
      final RadComponent component = container.getComponent(i);
      if (component instanceof RadContainer) {
        calcSelectedComponentsImpl(result, (RadContainer)component);
      }
      else {
        if (component.isSelected()) {
          result.add(component);
        }
      }
    }
  }

  /**
   * @return all selected component inside the editor
   */
  @NotNull
  public static ArrayList getAllSelectedComponents(@NotNull final GuiEditor editor) {
    final ArrayList result = new ArrayList();
    iterate(
      editor.getRootContainer(),
      new ComponentVisitor() {
        public boolean visit(final RadComponent component) {
          if (component.isSelected()) {
            result.add(component);
          }
          return true;
        }
      }
    );
    return result;
  }

  public static String getExceptionMessage(Throwable ex) {
    if (ex instanceof RuntimeException) {
      final Throwable cause = ex.getCause();
      if (cause != null && cause != ex) {
        return getExceptionMessage(cause);
      }
    }
    else if (ex instanceof InvocationTargetException) {
      final Throwable target = ((InvocationTargetException)ex).getTargetException();
      if (target != null && target != ex) {
        return getExceptionMessage(target);
      }
    }
    String message = ex.getMessage();
    if (ex instanceof ClassNotFoundException) {
      message =
        message != null ? UIDesignerBundle.message("error.class.not.found.N", message) : UIDesignerBundle.message("error.class.not.found");
    }
    else if (ex instanceof NoClassDefFoundError) {
      message = message != null
                ? UIDesignerBundle.message("error.required.class.not.found.N", message)
                : UIDesignerBundle.message("error.required.class.not.found");
    }
    return message;
  }

  public static IComponent findComponentWithBinding(IComponent component, final String binding) {
    return findComponentWithBinding(component, binding, null);
  }

  public static IComponent findComponentWithBinding(IComponent component,
                                                    final String binding,
                                                    @Nullable final IComponent exceptComponent) {
    // Check that binding is unique
    final Ref boundComponent = new Ref();
    iterate(
      component,
      new ComponentVisitor() {
        public boolean visit(final IComponent component) {
          if (component != exceptComponent && binding.equals(component.getBinding())) {
            boundComponent.set(component);
            return false;
          }
          return true;
        }
      }
    );

    return boundComponent.get();
  }

  @Nullable
  public static RadContainer getRadContainerAt(final RadRootContainer rootContainer, final int x, final int y,
                                               int epsilon) {
    RadComponent component = getRadComponentAt(rootContainer, x, y);
    if (isNullOrRoot(component) && epsilon > 0) {
      // try to find component near specified location
      component = getRadComponentAt(rootContainer, x - epsilon, y - epsilon);
      if (isNullOrRoot(component)) component = getRadComponentAt(rootContainer, x - epsilon, y + epsilon);
      if (isNullOrRoot(component)) component = getRadComponentAt(rootContainer, x + epsilon, y - epsilon);
      if (isNullOrRoot(component)) component = getRadComponentAt(rootContainer, x + epsilon, y + epsilon);
    }

    if (component != null) {
      return component instanceof RadContainer
             ? (RadContainer)component
             : component.getParent();
    }
    return null;
  }

  private static boolean isNullOrRoot(final RadComponent component) {
    return component == null || component instanceof RadRootContainer;
  }

  public static GridConstraints getDefaultConstraints(final RadComponent component) {
    final Palette palette = Palette.getInstance(component.getProject());
    final ComponentItem item = palette.getItem(component.getComponentClassName());
    if (item != null) {
      return item.getDefaultConstraints();
    }
    return new GridConstraints();
  }

  public static IRootContainer getRoot(IComponent component) {
    while (component != null) {
      if (component.getParentContainer() instanceof IRootContainer) {
        return (IRootContainer)component.getParentContainer();
      }
      component = component.getParentContainer();
    }
    return null;
  }

  /**
   * Iterates component and its children (if any)
   */
  public static void iterate(final IComponent component, final ComponentVisitor visitor) {
    iterateImpl(component, visitor);
  }

  private static boolean iterateImpl(final IComponent component, final ComponentVisitor visitor) {
    final boolean shouldContinue;
    try {
      shouldContinue = visitor.visit(component);
    }
    catch (ProcessCanceledException ex) {
      return false;
    }
    if (!shouldContinue) {
      return false;
    }

    if (!(component instanceof IContainer)) {
      return true;
    }

    final IContainer container = (IContainer)component;

    for (int i = 0; i < container.getComponentCount(); i++) {
      final IComponent c = container.getComponent(i);
      if (!iterateImpl(c, visitor)) {
        return false;
      }
    }

    return true;
  }

  public static Set collectUsedBundleNames(final IRootContainer rootContainer) {
    final Set bundleNames = new HashSet();
    iterateStringDescriptors(rootContainer, new StringDescriptorVisitor() {
      public boolean visit(final IComponent component, final StringDescriptor descriptor) {
        if (descriptor.getBundleName() != null && !bundleNames.contains(descriptor.getBundleName())) {
          bundleNames.add(descriptor.getBundleName());
        }
        return true;
      }
    });
    return bundleNames;
  }

  public static Locale[] collectUsedLocales(final Module module, final IRootContainer rootContainer) {
    final Set locales = new HashSet();
    final PropertiesReferenceManager propManager = PropertiesReferenceManager.getInstance(module.getProject());
    for (String bundleName : collectUsedBundleNames(rootContainer)) {
      List propFiles = propManager.findPropertiesFiles(module, bundleName.replace('/', '.'));
      for (PropertiesFile propFile : propFiles) {
        locales.add(propFile.getLocale());
      }
    }
    return locales.toArray(new Locale[locales.size()]);
  }

  public static void deleteRowOrColumn(final GuiEditor editor, final RadContainer container,
                                       final int[] cellsToDelete, final boolean isRow) {
    Arrays.sort(cellsToDelete);
    final int[] cells = ArrayUtil.reverseArray(cellsToDelete);
    if (!editor.ensureEditable()) {
      return;
    }

    Runnable runnable = new Runnable() {
      public void run() {
        if (!GridChangeUtil.canDeleteCells(container, cells, isRow)) {
          Set componentsInColumn = new HashSet();
          for (RadComponent component : container.getComponents()) {
            GridConstraints c = component.getConstraints();
            for (int cell : cells) {
              if (c.contains(isRow, cell)) {
                componentsInColumn.add(component);
                break;
              }
            }
          }

          if (componentsInColumn.size() > 0) {
            String message = isRow
                             ? UIDesignerBundle.message("delete.row.nonempty", componentsInColumn.size(), cells.length)
                             : UIDesignerBundle.message("delete.column.nonempty", componentsInColumn.size(), cells.length);

            final int rc = Messages.showYesNoDialog(editor, message,
                                                    isRow ? UIDesignerBundle.message("delete.row.title")
                                                          : UIDesignerBundle.message("delete.column.title"), Messages.getQuestionIcon());
            if (rc != Messages.YES) {
              return;
            }

            deleteComponents(componentsInColumn, false);
          }
        }

        for (int cell : cells) {
          container.getGridLayoutManager().deleteGridCells(container, cell, isRow);
        }
        editor.refreshAndSave(true);
      }
    };
    CommandProcessor.getInstance().executeCommand(editor.getProject(), runnable,
                                                  isRow ? UIDesignerBundle.message("command.delete.row")
                                                        : UIDesignerBundle.message("command.delete.column"), null);
  }

  /**
   * @param rootContainer
   * @return id
   */
  public static String generateId(final RadRootContainer rootContainer) {
    while (true) {
      final String id = Integer.toString((int)(Math.random() * 1024 * 1024), 16);
      if (findComponent(rootContainer, id) == null) {
        return id;
      }
    }
  }

  /**
   * @return {@link com.intellij.uiDesigner.designSurface.GuiEditor} from the context. Can be null.
   */
  @Nullable
  public static GuiEditor getEditorFromContext(@NotNull final DataContext context) {
    final FileEditor editor = PlatformDataKeys.FILE_EDITOR.getData(context);
    if (editor instanceof UIFormEditor) {
      return ((UIFormEditor)editor).getEditor();
    }
    else {
      return GuiEditor.DATA_KEY.getData(context);
    }
  }

  @Nullable
  public static GuiEditor getActiveEditor(final DataContext context) {
    Project project = CommonDataKeys.PROJECT.getData(context);
    if (project == null) {
      return null;
    }
    final DesignerToolWindowManager toolWindowManager = DesignerToolWindowManager.getInstance(project);
    if (toolWindowManager == null) {
      return null;
    }
    return toolWindowManager.getActiveFormEditor();
  }

  /**
   * @param componentToAssignBinding
   * @param binding
   * @param component                topmost container where to find duplicate binding. In most cases
   *                                 it should be {@link com.intellij.uiDesigner.designSurface.GuiEditor#getRootContainer()}
   */
  public static boolean isBindingUnique(
    final IComponent componentToAssignBinding,
    final String binding,
    final IComponent component
  ) {
    return findComponentWithBinding(component, binding, componentToAssignBinding) == null;
  }

  @Nullable
  public static String buildResourceName(final PsiFile file) {
    PsiDirectory directory = file.getContainingDirectory();
    if (directory != null) {
      PsiPackage pkg = JavaDirectoryService.getInstance().getPackage(directory);
      String packageName = pkg != null ? pkg.getQualifiedName() : "";
      if (packageName.length() == 0) {
        return file.getName();
      }
      return packageName.replace('.', '/') + '/' + file.getName();
    }
    return null;
  }

  @Nullable
  public static RadContainer getSelectionParent(final List selection) {
    RadContainer parent = null;
    for (RadComponent c : selection) {
      if (parent == null) {
        parent = c.getParent();
      }
      else if (parent != c.getParent()) {
        parent = null;
        break;
      }
    }
    return parent;
  }

  public static Rectangle getSelectionBounds(List selection) {
    int minRow = Integer.MAX_VALUE;
    int minCol = Integer.MAX_VALUE;
    int maxRow = 0;
    int maxCol = 0;

    for (RadComponent c : selection) {
      minRow = Math.min(minRow, c.getConstraints().getRow());
      minCol = Math.min(minCol, c.getConstraints().getColumn());
      maxRow = Math.max(maxRow, c.getConstraints().getRow() + c.getConstraints().getRowSpan());
      maxCol = Math.max(maxCol, c.getConstraints().getColumn() + c.getConstraints().getColSpan());
    }
    return new Rectangle(minCol, minRow, maxCol - minCol, maxRow - minRow);
  }

  public static boolean isComponentSwitchedInView(@NotNull RadComponent component) {
    while (component.getParent() != null) {
      if (!component.getParent().getLayoutManager().isSwitchedToChild(component.getParent(), component)) {
        return false;
      }
      component = component.getParent();
    }
    return true;
  }

  /**
   * Selects the component and ensures that the tabbed panes containing the component are
   * switched to the correct tab.
   *
   * @param editor
   * @param component the component to select. @return true if the component is enclosed in at least one tabbed pane, false otherwise.
   */
  public static boolean selectComponent(final GuiEditor editor, @NotNull final RadComponent component) {
    boolean hasTab = false;
    RadComponent parent = component;
    while (parent.getParent() != null) {
      if (parent.getParent().getLayoutManager().switchContainerToChild(parent.getParent(), parent)) {
        hasTab = true;
      }
      parent = parent.getParent();
    }
    component.setSelected(true);
    editor.setSelectionLead(component);
    return hasTab;
  }

  public static void selectSingleComponent(final GuiEditor editor, final RadComponent component) {
    final RadContainer root = (RadContainer)getRoot(component);
    if (root == null) return;

    ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder();
    // this can return null if the click to select the control also requested to grab the focus -
    // the component tree will be instantiated after the event has been processed completely
    if (builder != null) {
      builder.beginUpdateSelection();
    }
    try {
      clearSelection(root);
      selectComponent(editor, component);
      editor.setSelectionAnchor(component);
      editor.scrollComponentInView(component);
    }
    finally {
      if (builder != null) {
        builder.endUpdateSelection();
      }
    }
  }

  public static void selectComponents(final GuiEditor editor, List components) {
    if (components.size() > 0) {
      RadComponent component = components.get(0);
      ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder();
      if (builder == null) {
        // race condition when handling event?
        return;
      }
      builder.beginUpdateSelection();
      try {
        clearSelection((RadContainer)getRoot(component));
        for (RadComponent aComponent : components) {
          selectComponent(editor, aComponent);
        }
      }
      finally {
        builder.endUpdateSelection();
      }
    }
  }

  public static boolean isDropOnChild(final DraggedComponentList draggedComponentList,
                                      final ComponentDropLocation location) {
    if (location.getContainer() == null) {
      return false;
    }

    for (RadComponent component : draggedComponentList.getComponents()) {
      if (isChild(location.getContainer(), component)) {
        return true;
      }
    }
    return false;
  }

  private static boolean isChild(RadContainer maybeChild, RadComponent maybeParent) {
    while (maybeChild != null) {
      if (maybeParent == maybeChild) {
        return true;
      }
      maybeChild = maybeChild.getParent();
    }
    return false;
  }

  public static PsiMethod findCreateComponentsMethod(final PsiClass aClass) {
    PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
    PsiMethod method;
    try {
      method = factory.createMethodFromText("void " + AsmCodeGenerator.CREATE_COMPONENTS_METHOD_NAME + "() {}",
                                            aClass);
    }
    catch (IncorrectOperationException e) {
      throw new RuntimeException(e);
    }
    return aClass.findMethodBySignature(method, true);
  }

  public static Object getNextSaveUndoGroupId(final Project project) {
    final GuiEditor guiEditor = DesignerToolWindowManager.getInstance(project).getActiveFormEditor();
    return guiEditor == null ? null : guiEditor.getNextSaveGroupId();
  }

  public static int adjustForGap(final RadContainer container, final int cellIndex, final boolean isRow, final int delta) {
    if (container.getGridLayoutManager().isGapCell(container, isRow, cellIndex)) {
      return cellIndex + delta;
    }
    return cellIndex;
  }

  public static int prevRow(final RadContainer container, final int row) {
    return adjustForGap(container, row - 1, true, -1);
  }

  public static int nextRow(final RadContainer container, final int row) {
    return adjustForGap(container, row + 1, true, 1);
  }

  public static int prevCol(final RadContainer container, final int col) {
    return adjustForGap(container, col - 1, false, -1);
  }

  public static int nextCol(final RadContainer container, final int col) {
    return adjustForGap(container, col + 1, false, 1);
  }

  @Nullable
  public static IButtonGroup findGroupForComponent(final IRootContainer radRootContainer, @NotNull final IComponent component) {
    for (IButtonGroup group : radRootContainer.getButtonGroups()) {
      for (String id : group.getComponentIds()) {
        if (component.getId().equals(id)) {
          return group;
        }
      }
    }
    return null;
  }

  public static void remapToActionTargets(final List selection) {
    for (int i = 0; i < selection.size(); i++) {
      final RadComponent c = selection.get(i);
      if (c.getParent() != null) {
        selection.set(i, c.getParent().getActionTargetComponent(c));
      }
    }
  }

  public static void showPopupUnderComponent(final JBPopup popup, final RadComponent selectedComponent) {
    // popup.showUnderneathOf() doesn't work on invisible components
    Rectangle rc = selectedComponent.getBounds();
    Point pnt = new Point(rc.x, rc.y + rc.height);
    popup.show(new RelativePoint(selectedComponent.getDelegee().getParent(), pnt));
  }

  public interface StringDescriptorVisitor {
    boolean visit(T component, StringDescriptor descriptor);
  }


  public static void iterateStringDescriptors(final IComponent component,
                                              final StringDescriptorVisitor visitor) {
    iterate(component, new ComponentVisitor() {

      public boolean visit(final IComponent component) {
        for (IProperty prop : component.getModifiedProperties()) {
          Object value = prop.getPropertyValue(component);
          if (value instanceof StringDescriptor) {
            if (!visitor.visit(component, (StringDescriptor)value)) {
              return false;
            }
          }
        }
        if (component.getParentContainer() instanceof ITabbedPane) {
          StringDescriptor tabTitle =
            ((ITabbedPane)component.getParentContainer()).getTabProperty(component, ITabbedPane.TAB_TITLE_PROPERTY);
          if (tabTitle != null && !visitor.visit(component, tabTitle)) {
            return false;
          }
          StringDescriptor tabToolTip =
            ((ITabbedPane)component.getParentContainer()).getTabProperty(component, ITabbedPane.TAB_TOOLTIP_PROPERTY);
          if (tabToolTip != null && !visitor.visit(component, tabToolTip)) {
            return false;
          }
        }
        if (component instanceof IContainer) {
          final StringDescriptor borderTitle = ((IContainer)component).getBorderTitle();
          if (borderTitle != null && !visitor.visit(component, borderTitle)) {
            return false;
          }
        }
        return true;
      }
    });
  }

  public static void clearSelection(@NotNull final RadContainer container) {
    container.setSelected(false);

    for (int i = 0; i < container.getComponentCount(); i++) {
      final RadComponent c = container.getComponent(i);
      if (c instanceof RadContainer) {
        clearSelection((RadContainer)c);
      }
      else {
        c.setSelected(false);
      }
    }
  }

  /**
   * Finds component with the specified id starting from the
   * container. The method goes recursively through the hierarchy
   * of components. Note, that if container itself has id
   * then the method immediately retuns it.
   *
   * @return the found component.
   */
  @Nullable
  public static IComponent findComponent(@NotNull final IComponent component, @NotNull final String id) {
    if (id.equals(component.getId())) {
      return component;
    }
    if (!(component instanceof IContainer)) {
      return null;
    }

    final IContainer uiContainer = (IContainer)component;
    for (int i = 0; i < uiContainer.getComponentCount(); i++) {
      final IComponent found = findComponent(uiContainer.getComponent(i), id);
      if (found != null) {
        return found;
      }
    }
    return null;
  }

  @Nullable
  public static PsiClass findClassToBind(@NotNull final Module module, @NotNull final String classToBindName) {
    return JavaPsiFacade.getInstance(module.getProject())
      .findClass(classToBindName.replace('$', '.'), module.getModuleWithDependenciesScope());
  }

  public interface ComponentVisitor {
    /**
     * @return true if iteration should continue
     */
    boolean visit(Type component);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy