@Override
  protected ValidationInfo doValidate() {
    final String resourceName = getResourceName();
    final Module selectedModule = getModule();
    final List<String> directoryNames = getDirNames();
    final String fileName = getFileName();

    if (resourceName.length() == 0) {
      return new ValidationInfo("specify resource name", myNameField);
    } else if (!AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) {
      return new ValidationInfo(resourceName + " is not correct resource name", myNameField);
    } else if (fileName.length() == 0) {
      return new ValidationInfo("specify file name", myFileNameCombo);
    } else if (selectedModule == null) {
      return new ValidationInfo("specify module", myModuleCombo);
    } else if (directoryNames.size() == 0) {
      return new ValidationInfo("choose directories", myDirectoriesList);
    }

    final ValidationInfo info =
        checkIfResourceAlreadyExists(
            selectedModule, resourceName, myResourceType, directoryNames, fileName);
    if (info != null) {
      return info;
    }
    return null;
  }
 private static List<TreePath> getPaths(BreakpointTree tree, final Object[] userObjects) {
   final List<TreePath> paths = new ArrayList<TreePath>(userObjects.length);
   for (Object descriptor : userObjects) {
     final CheckedTreeNode node = tree.myDescriptorToNodeMap.get(descriptor);
     if (node != null) {
       paths.add(new TreePath(node.getPath()));
     }
   }
   return paths;
 }
  @NotNull
  public List<String> getDirNames() {
    final List<String> selectedDirs = new ArrayList<String>();

    for (Map.Entry<String, JCheckBox> entry : myCheckBoxes.entrySet()) {
      if (entry.getValue().isSelected()) {
        selectedDirs.add(entry.getKey());
      }
    }
    return selectedDirs;
  }
 @Override
 protected void doOKAction() {
   final String errorString = myComponent.canCreateAllFilesForAllLocales();
   if (errorString != null) {
     Messages.showErrorDialog(getContentPanel(), errorString);
   } else {
     final List<PsiFile> createFiles = myComponent.createPropertiesFiles();
     myCreatedFiles = createFiles.toArray(new PsiElement[createFiles.size()]);
     super.doOKAction();
   }
 }
 public void selectBreakpoints(Breakpoint[] breakpoints) {
   final List<CheckedTreeNode> nodes = new ArrayList<CheckedTreeNode>(breakpoints.length);
   for (Breakpoint breakpoint : breakpoints) {
     final CheckedTreeNode node = myDescriptorToNodeMap.get(new BreakpointDescriptor(breakpoint));
     if (node != null) {
       nodes.add(node);
     }
   }
   clearSelection();
   for (CheckedTreeNode node : nodes) {
     addSelectionPath(new TreePath(node.getPath()));
   }
 }
 private void rebuildTree() {
   final TreeStateSnapshot treeStateSnapshot = new TreeStateSnapshot(this);
   myRootNode.removeAllChildren();
   myDescriptorToNodeMap.clear();
   myDescriptorToNodeMap.put((TreeDescriptor) myRootNode.getUserObject(), myRootNode);
   // build tree
   for (final Breakpoint breakpoint : myBreakpoints) {
     CheckedTreeNode node = createNode(new BreakpointDescriptor(breakpoint));
     node.setChecked(breakpoint.ENABLED);
     addNode(node);
   }
   // remove all package nodes with one child
   final int count = myRootNode.getChildCount();
   final List<CheckedTreeNode> children = new ArrayList<CheckedTreeNode>();
   for (int idx = 0; idx < count; idx++) {
     CheckedTreeNode child = (CheckedTreeNode) myRootNode.getChildAt(idx);
     if (!(child.getUserObject() instanceof PackageDescriptor)) {
       children.add(child);
       continue;
     }
     while (child.getUserObject() instanceof PackageDescriptor && child.getChildCount() <= 1) {
       child = (CheckedTreeNode) child.getChildAt(0);
     }
     if (!(child.getUserObject() instanceof PackageDescriptor)) {
       child = (CheckedTreeNode) child.getParent();
     }
     for (CheckedTreeNode childToRemove = (CheckedTreeNode) child.getParent();
         !childToRemove.equals(myRootNode);
         childToRemove = (CheckedTreeNode) childToRemove.getParent()) {
       myDescriptorToNodeMap.remove(childToRemove.getUserObject());
     }
     children.add(child);
   }
   for (final CheckedTreeNode aChildren : children) {
     aChildren.removeFromParent();
   }
   myRootNode.removeAllChildren();
   for (final CheckedTreeNode child : children) {
     myRootNode.add(child);
   }
   sortChildren(myRootNode);
   ((DefaultTreeModel) getModel()).nodeStructureChanged(myRootNode);
   treeStateSnapshot.restore(this);
   expandPath(new TreePath(myRootNode));
 }
 private void sortChildren(CheckedTreeNode node) {
   final int childCount = node.getChildCount();
   if (childCount == 0) {
     return;
   }
   final List<CheckedTreeNode> children = new ArrayList<CheckedTreeNode>(childCount);
   for (int idx = 0; idx < childCount; idx++) {
     children.add((CheckedTreeNode) node.getChildAt(idx));
   }
   for (CheckedTreeNode child : children) {
     sortChildren(child);
     child.removeFromParent();
   }
   Collections.sort(children, myNodeComparator);
   for (CheckedTreeNode child : children) {
     node.add(child);
   }
 }
  @Nullable
  private static List<Locale> extractLocalesFromString(final String rawLocales) {
    if (rawLocales.isEmpty()) {
      return Collections.emptyList();
    }
    final String[] splitRawLocales = rawLocales.split(",");
    final List<Locale> locales = new ArrayList<>(splitRawLocales.length);

    for (String rawLocale : splitRawLocales) {
      final Locale locale = PropertiesUtil.getLocale("_" + rawLocale + ".properties");
      if (locale == PropertiesUtil.DEFAULT_LOCALE) {
        return null;
      } else if (!locales.contains(locale)) {
        locales.add(locale);
      }
    }
    return locales;
  }
  @Nullable
  public static ValidationInfo checkIfResourceAlreadyExists(
      @NotNull Module selectedModule,
      @NotNull String resourceName,
      @NotNull ResourceType resourceType,
      @NotNull List<String> dirNames,
      @NotNull String fileName) {
    if (resourceName.length() == 0 || dirNames.size() == 0 || fileName.length() == 0) {
      return null;
    }

    final AndroidFacet facet = AndroidFacet.getInstance(selectedModule);
    final VirtualFile resourceDir = facet != null ? AndroidRootUtil.getResourceDir(facet) : null;
    if (resourceDir == null) {
      return null;
    }

    for (String directoryName : dirNames) {
      final VirtualFile resourceSubdir = resourceDir.findChild(directoryName);
      if (resourceSubdir == null) {
        continue;
      }

      final VirtualFile resFile = resourceSubdir.findChild(fileName);
      if (resFile == null) {
        continue;
      }

      if (resFile.getFileType() != StdFileTypes.XML) {
        return new ValidationInfo(
            "File " + FileUtil.toSystemDependentName(resFile.getPath()) + " is not XML file");
      }

      final Resources resources =
          AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class);
      if (resources == null) {
        return new ValidationInfo(
            AndroidBundle.message(
                "not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath())));
      }

      for (ResourceElement element :
          AndroidResourceUtil.getValueResourcesFromElement(resourceType.getName(), resources)) {
        if (resourceName.equals(element.getName().getValue())) {
          return new ValidationInfo(
              "resource '"
                  + resourceName
                  + "' already exists in "
                  + FileUtil.toSystemDependentName(resFile.getPath()));
        }
      }
    }
    return null;
  }
 public void addBreakpoint(final Breakpoint breakpoint) {
   myBreakpoints.add(breakpoint);
   breakpoint.updateUI(
       new Runnable() {
         public void run() {
           rebuildTree();
         }
       });
   rebuildTree();
   selectBreakpoint(breakpoint);
 }
  private void combineToResourceBundleIfNeed(Collection<PsiFile> files) {
    Collection<PropertiesFile> createdFiles =
        ContainerUtil.map(
            files,
            (NotNullFunction<PsiFile, PropertiesFile>)
                dom -> {
                  final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(dom);
                  LOG.assertTrue(file != null, dom.getName());
                  return file;
                });

    ResourceBundle mainBundle = myResourceBundle;
    final Set<ResourceBundle> allBundles = new HashSet<>();
    if (mainBundle != null) {
      allBundles.add(mainBundle);
    }
    boolean needCombining = false;
    for (PropertiesFile file : createdFiles) {
      final ResourceBundle rb = file.getResourceBundle();
      if (mainBundle == null) {
        mainBundle = rb;
      } else if (!mainBundle.equals(rb)) {
        needCombining = true;
      }
      allBundles.add(rb);
    }

    if (needCombining) {
      final List<PropertiesFile> toCombine = new ArrayList<>(createdFiles);
      final String baseName = getBaseName();
      if (myResourceBundle != null) {
        toCombine.addAll(myResourceBundle.getPropertiesFiles());
      }
      ResourceBundleManager manager = ResourceBundleManager.getInstance(mainBundle.getProject());
      for (ResourceBundle bundle : allBundles) {
        manager.dissociateResourceBundle(bundle);
      }
      manager.combineToResourceBundle(toCombine, baseName);
    }
  }
 public Breakpoint[] getSelectedBreakpoints() {
   final TreePath[] selectionPaths = getSelectionPaths();
   if (selectionPaths == null || selectionPaths.length == 0) {
     return Breakpoint.EMPTY_ARRAY;
   }
   final List<Breakpoint> breakpoints = new ArrayList<Breakpoint>(selectionPaths.length);
   for (TreePath path : selectionPaths) {
     final CheckedTreeNode node = (CheckedTreeNode) path.getLastPathComponent();
     TreeUtil.traverseDepth(
         node,
         new TreeUtil.Traverse() {
           public boolean accept(Object _node) {
             final CheckedTreeNode node = (CheckedTreeNode) _node;
             final TreeDescriptor descriptor = (TreeDescriptor) node.getUserObject();
             if (descriptor instanceof BreakpointDescriptor) {
               breakpoints.add(((BreakpointDescriptor) descriptor).getBreakpoint());
             }
             return true;
           }
         });
   }
   return breakpoints.toArray(new Breakpoint[breakpoints.size()]);
 }
  @Override
  protected void doOKAction() {
    final String resourceName = getResourceName();
    final String fileName = getFileName();
    final List<String> dirNames = getDirNames();
    final Module module = getModule();

    if (resourceName.length() == 0) {
      Messages.showErrorDialog(
          myPanel, "Resource name is not specified", CommonBundle.getErrorTitle());
    } else if (!AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) {
      Messages.showErrorDialog(
          myPanel, resourceName + " is not correct resource name", CommonBundle.getErrorTitle());
    } else if (fileName.length() == 0) {
      Messages.showErrorDialog(myPanel, "File name is not specified", CommonBundle.getErrorTitle());
    } else if (dirNames.size() == 0) {
      Messages.showErrorDialog(
          myPanel, "Directories are not selected", CommonBundle.getErrorTitle());
    } else if (module == null) {
      Messages.showErrorDialog(myPanel, "Module is not specified", CommonBundle.getErrorTitle());
    } else {
      super.doOKAction();
    }
  }
    public void restore(BreakpointTree tree) {
      final List<TreePath> pathsToExpand = getPaths(tree, myExpandedUserObjects);
      if (!pathsToExpand.isEmpty()) {
        TreeUtil.restoreExpandedPaths(tree, pathsToExpand);
      }

      final List<TreePath> pathsToSelect = getPaths(tree, mySelectedUserObjects);
      if (!pathsToSelect.isEmpty()) {
        tree.getSelectionModel().clearSelection();
        tree.setSelectionPaths(pathsToSelect.toArray(new TreePath[pathsToSelect.size()]));
      }
    }
 private MyExistLocalesListModel() {
   myLocales = new ArrayList<>();
   myLocales.add(PropertiesUtil.DEFAULT_LOCALE);
   PropertiesReferenceManager.getInstance(myProject)
       .processPropertiesFiles(
           GlobalSearchScope.projectScope(myProject),
           new PropertiesFileProcessor() {
             @Override
             public boolean process(String baseName, PropertiesFile propertiesFile) {
               final Locale locale = propertiesFile.getLocale();
               if (locale != PropertiesUtil.DEFAULT_LOCALE && !myLocales.contains(locale)) {
                 myLocales.add(locale);
               }
               return true;
             }
           },
           BundleNameEvaluator.DEFAULT);
   Collections.sort(myLocales, LOCALE_COMPARATOR);
 }
  @Nullable
  private DependencyOnPlugin editPluginDependency(
      @NotNull JComponent parent, @NotNull final DependencyOnPlugin original) {
    List<String> pluginIds = new ArrayList<String>(getPluginNameByIdMap().keySet());
    if (!original.getPluginId().isEmpty() && !pluginIds.contains(original.getPluginId())) {
      pluginIds.add(original.getPluginId());
    }
    Collections.sort(
        pluginIds,
        new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            return getPluginNameById(o1).compareToIgnoreCase(getPluginNameById(o2));
          }
        });

    final ComboBox pluginChooser = new ComboBox(ArrayUtilRt.toStringArray(pluginIds), 250);
    pluginChooser.setRenderer(
        new ListCellRendererWrapper<String>() {
          @Override
          public void customize(
              JList list, String value, int index, boolean selected, boolean hasFocus) {
            setText(getPluginNameById(value));
          }
        });
    new ComboboxSpeedSearch(pluginChooser) {
      @Override
      protected String getElementText(Object element) {
        return getPluginNameById((String) element);
      }
    };
    pluginChooser.setSelectedItem(original.getPluginId());

    final JBTextField minVersionField =
        new JBTextField(StringUtil.notNullize(original.getMinVersion()));
    final JBTextField maxVersionField =
        new JBTextField(StringUtil.notNullize(original.getMaxVersion()));
    final JBTextField channelField = new JBTextField(StringUtil.notNullize(original.getChannel()));
    minVersionField.getEmptyText().setText("<any>");
    minVersionField.setColumns(10);
    maxVersionField.getEmptyText().setText("<any>");
    maxVersionField.setColumns(10);
    channelField.setColumns(10);
    JPanel panel =
        FormBuilder.createFormBuilder()
            .addLabeledComponent("Plugin:", pluginChooser)
            .addLabeledComponent("Minimum version:", minVersionField)
            .addLabeledComponent("Maximum version:", maxVersionField)
            .addLabeledComponent("Channel:", channelField)
            .getPanel();
    final DialogBuilder dialogBuilder =
        new DialogBuilder(parent).title("Required Plugin").centerPanel(panel);
    dialogBuilder.setPreferredFocusComponent(pluginChooser);
    pluginChooser.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            dialogBuilder.setOkActionEnabled(
                !StringUtil.isEmpty((String) pluginChooser.getSelectedItem()));
          }
        });
    if (dialogBuilder.show() == DialogWrapper.OK_EXIT_CODE) {
      return new DependencyOnPlugin(
          ((String) pluginChooser.getSelectedItem()),
          StringUtil.nullize(minVersionField.getText().trim()),
          StringUtil.nullize(maxVersionField.getText().trim()),
          StringUtil.nullize(channelField.getText().trim()));
    }
    return null;
  }
 public TreeStateSnapshot(BreakpointTree tree) {
   final List<TreePath> expandedPaths = TreeUtil.collectExpandedPaths(tree);
   myExpandedUserObjects =
       getUserObjects(expandedPaths.toArray(new TreePath[expandedPaths.size()]));
   mySelectedUserObjects = getUserObjects(tree.getSelectionPaths());
 }
 @Override
 public int getSize() {
   return myLocales.size();
 }
 @Override
 public Locale getElementAt(int index) {
   return myLocales.get(index);
 }
 public void setBreakpoints(Breakpoint[] breakpoints) {
   myBreakpoints.clear();
   ContainerUtil.addAll(myBreakpoints, breakpoints);
   rebuildTree();
 }
 public void removeBreakpoints(Breakpoint[] breakpoints) {
   myBreakpoints.removeAll(Arrays.asList(breakpoints));
   rebuildTree();
 }
 public void removeBreakpoint(Breakpoint breakpoint) {
   myBreakpoints.remove(breakpoint);
   rebuildTree();
 }
  private void updateDirectories(boolean updateFileCombo) {
    final Module module = getModule();
    List<VirtualFile> valuesDirs = Collections.emptyList();

    if (module != null) {
      final AndroidFacet facet = AndroidFacet.getInstance(module);

      if (facet != null) {
        myResourceDir = AndroidRootUtil.getResourceDir(facet);

        if (myResourceDir != null) {
          valuesDirs =
              AndroidResourceUtil.getResourceSubdirs(
                  ResourceFolderType.VALUES.getName(), new VirtualFile[] {myResourceDir});
        }
      }
    }

    Collections.sort(
        valuesDirs,
        new Comparator<VirtualFile>() {
          @Override
          public int compare(VirtualFile f1, VirtualFile f2) {
            return f1.getName().compareTo(f2.getName());
          }
        });

    final Map<String, JCheckBox> oldCheckBoxes = myCheckBoxes;
    final int selectedIndex = myDirectoriesList.getSelectedIndex();
    final String selectedDirName = selectedIndex >= 0 ? myDirNames[selectedIndex] : null;

    final List<JCheckBox> checkBoxList = new ArrayList<JCheckBox>();
    myCheckBoxes = new HashMap<String, JCheckBox>();
    myDirNames = new String[valuesDirs.size()];

    int newSelectedIndex = -1;

    int i = 0;

    for (VirtualFile dir : valuesDirs) {
      final String dirName = dir.getName();
      final JCheckBox oldCheckBox = oldCheckBoxes.get(dirName);
      final boolean selected = oldCheckBox != null && oldCheckBox.isSelected();
      final JCheckBox checkBox = new JCheckBox(dirName, selected);
      checkBoxList.add(checkBox);
      myCheckBoxes.put(dirName, checkBox);
      myDirNames[i] = dirName;

      if (dirName.equals(selectedDirName)) {
        newSelectedIndex = i;
      }
      i++;
    }
    myDirectoriesList.setModel(new CollectionListModel<JCheckBox>(checkBoxList));

    if (newSelectedIndex >= 0) {
      myDirectoriesList.setSelectedIndex(newSelectedIndex);
    }

    if (checkBoxList.size() == 1) {
      checkBoxList.get(0).setSelected(true);
    }

    if (updateFileCombo) {
      final Object oldItem = myFileNameCombo.getEditor().getItem();
      final Set<String> fileNameSet = new HashSet<String>();

      for (VirtualFile valuesDir : valuesDirs) {
        for (VirtualFile file : valuesDir.getChildren()) {
          fileNameSet.add(file.getName());
        }
      }
      final List<String> fileNames = new ArrayList<String>(fileNameSet);
      Collections.sort(fileNames);
      myFileNameCombo.setModel(new DefaultComboBoxModel(fileNames.toArray()));
      myFileNameCombo.getEditor().setItem(oldItem);
    }
  }