simplify GTDUCollector a bit more
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / configuration / artifacts / ArtifactEditorImpl.java
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.roots.ui.configuration.artifacts;
3
4 import com.intellij.codeInsight.hint.HintManager;
5 import com.intellij.codeInsight.hint.HintUtil;
6 import com.intellij.icons.AllIcons;
7 import com.intellij.ide.CommonActionsManager;
8 import com.intellij.ide.DataManager;
9 import com.intellij.ide.DefaultTreeExpander;
10 import com.intellij.ide.JavaUiBundle;
11 import com.intellij.ide.impl.TypeSafeDataProviderAdapter;
12 import com.intellij.openapi.actionSystem.*;
13 import com.intellij.openapi.compiler.JavaCompilerBundle;
14 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
15 import com.intellij.openapi.module.Module;
16 import com.intellij.openapi.project.Project;
17 import com.intellij.openapi.roots.libraries.Library;
18 import com.intellij.openapi.roots.ui.configuration.artifacts.actions.*;
19 import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.LibrarySourceItem;
20 import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.ModuleOutputSourceItem;
21 import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.SourceItemsTree;
22 import com.intellij.openapi.ui.FixedSizeButton;
23 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
24 import com.intellij.openapi.util.Disposer;
25 import com.intellij.openapi.util.io.FileUtil;
26 import com.intellij.openapi.util.io.FileUtilRt;
27 import com.intellij.openapi.util.text.StringUtil;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.packaging.artifacts.Artifact;
30 import com.intellij.packaging.artifacts.ArtifactType;
31 import com.intellij.packaging.artifacts.ModifiableArtifact;
32 import com.intellij.packaging.elements.*;
33 import com.intellij.packaging.impl.artifacts.ArtifactUtil;
34 import com.intellij.packaging.impl.elements.ArchivePackagingElement;
35 import com.intellij.packaging.impl.elements.ManifestFileUtil;
36 import com.intellij.packaging.ui.ManifestFileConfiguration;
37 import com.intellij.ui.*;
38 import com.intellij.ui.awt.RelativePoint;
39 import com.intellij.ui.border.CustomLineBorder;
40 import com.intellij.util.EventDispatcher;
41 import com.intellij.util.IconUtil;
42 import com.intellij.util.ui.JBUI;
43 import com.intellij.util.ui.StartupUiUtil;
44 import com.intellij.util.ui.ThreeStateCheckBox;
45 import com.intellij.util.ui.UIUtil;
46 import org.jetbrains.annotations.NotNull;
47 import org.jetbrains.annotations.Nullable;
48
49 import javax.swing.*;
50 import javax.swing.border.CompoundBorder;
51 import javax.swing.border.LineBorder;
52 import javax.swing.event.DocumentEvent;
53 import javax.swing.event.HyperlinkEvent;
54 import java.awt.*;
55 import java.awt.event.ActionEvent;
56 import java.awt.event.ActionListener;
57 import java.util.ArrayList;
58 import java.util.Collections;
59 import java.util.List;
60 import java.util.Objects;
61
62 public class ArtifactEditorImpl implements ArtifactEditorEx {
63   private JPanel myMainPanel;
64   private JCheckBox myBuildOnMakeCheckBox;
65   private TextFieldWithBrowseButton myOutputDirectoryField;
66   private JPanel myEditorPanel;
67   private JPanel myErrorPanelPlace;
68   private ThreeStateCheckBox myShowContentCheckBox;
69   private FixedSizeButton myShowSpecificContentOptionsButton;
70   private JPanel myTopPanel;
71   private final ActionGroup myShowSpecificContentOptionsGroup;
72   private final Project myProject;
73   private final ComplexElementSubstitutionParameters mySubstitutionParameters = new ComplexElementSubstitutionParameters();
74   private final EventDispatcher<ArtifactEditorListener> myDispatcher = EventDispatcher.create(ArtifactEditorListener.class);
75   private final ArtifactEditorContextImpl myContext;
76   private final SourceItemsTree mySourceItemsTree;
77   private final Artifact myOriginalArtifact;
78   private final LayoutTreeComponent myLayoutTreeComponent;
79   private TabbedPaneWrapper myTabbedPane;
80   private ArtifactPropertiesEditors myPropertiesEditors;
81   private final ArtifactValidationManagerImpl myValidationManager;
82   private boolean myDisposed;
83
84   public ArtifactEditorImpl(final @NotNull ArtifactsStructureConfigurableContext context, @NotNull Artifact artifact, @NotNull ArtifactEditorSettings settings) {
85     myContext = createArtifactEditorContext(context);
86     myOriginalArtifact = artifact;
87     myProject = context.getProject();
88     myValidationManager = new ArtifactValidationManagerImpl(this);
89     mySubstitutionParameters.setTypesToShowContent(settings.getTypesToShowContent());
90     mySourceItemsTree = new SourceItemsTree(myContext, this);
91     myLayoutTreeComponent = new LayoutTreeComponent(this, mySubstitutionParameters, myContext, myOriginalArtifact, settings.isSortElements());
92     myPropertiesEditors = new ArtifactPropertiesEditors(myContext, myOriginalArtifact, myOriginalArtifact);
93     Disposer.register(this, mySourceItemsTree);
94     Disposer.register(this, myLayoutTreeComponent);
95     myTopPanel.setBorder(JBUI.Borders.empty(0, 10));
96     myBuildOnMakeCheckBox.setSelected(artifact.isBuildOnMake());
97     final String outputPath = artifact.getOutputPath();
98     myOutputDirectoryField.addBrowseFolderListener(JavaCompilerBundle.message("dialog.title.output.directory.for.artifact"),
99                                                    JavaCompilerBundle.message("chooser.description.select.output.directory.for.0.artifact",
100                                                                               getArtifact().getName()), myProject,
101                                                    FileChooserDescriptorFactory.createSingleFolderDescriptor());
102     myOutputDirectoryField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
103       @Override
104       protected void textChanged(@NotNull DocumentEvent e) {
105         queueValidation();
106       }
107     });
108     myOutputDirectoryField.getTextField().getAccessibleContext().setAccessibleName(JavaUiBundle.message("label.text.output.directory"));
109     myShowSpecificContentOptionsGroup = createShowSpecificContentOptionsGroup();
110     myShowSpecificContentOptionsButton.addActionListener(new ActionListener() {
111       @Override
112       public void actionPerformed(ActionEvent e) {
113         ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, myShowSpecificContentOptionsGroup).getComponent().show(myShowSpecificContentOptionsButton, 0, 0);
114       }
115     });
116     setOutputPath(outputPath);
117     updateShowContentCheckbox();
118   }
119
120   protected ArtifactEditorContextImpl createArtifactEditorContext(ArtifactsStructureConfigurableContext parentContext) {
121     return new ArtifactEditorContextImpl(parentContext, this);
122   }
123
124   private ActionGroup createShowSpecificContentOptionsGroup() {
125     final DefaultActionGroup group = new DefaultActionGroup();
126     for (ComplexPackagingElementType<?> type : PackagingElementFactory.getInstance().getComplexElementTypes()) {
127       group.add(new ToggleShowElementContentAction(type, this));
128     }
129     return group;
130   }
131
132   private void setOutputPath(@Nullable String outputPath) {
133     myOutputDirectoryField.setText(outputPath != null ? FileUtil.toSystemDependentName(outputPath) : null);
134   }
135
136   public void apply() {
137     final ModifiableArtifact modifiableArtifact = myContext.getOrCreateModifiableArtifactModel().getOrCreateModifiableArtifact(myOriginalArtifact);
138     modifiableArtifact.setBuildOnMake(myBuildOnMakeCheckBox.isSelected());
139     modifiableArtifact.setOutputPath(getConfiguredOutputPath());
140     myPropertiesEditors.applyProperties();
141     myLayoutTreeComponent.saveElementProperties();
142   }
143
144   @Nullable
145   private String getConfiguredOutputPath() {
146     String outputPath = FileUtil.toSystemIndependentName(myOutputDirectoryField.getText().trim());
147     if (outputPath.length() == 0) {
148       outputPath = null;
149     }
150     return outputPath;
151   }
152
153   public SourceItemsTree getSourceItemsTree() {
154     return mySourceItemsTree;
155   }
156
157   public void addListener(@NotNull final ArtifactEditorListener listener) {
158     myDispatcher.addListener(listener);
159   }
160
161   @Override
162   public ArtifactEditorContextImpl getContext() {
163     return myContext;
164   }
165
166   public void removeListener(@NotNull final ArtifactEditorListener listener) {
167     myDispatcher.removeListener(listener);
168   }
169
170   @Override
171   public Artifact getArtifact() {
172     return myContext.getArtifactModel().getArtifactByOriginal(myOriginalArtifact);
173   }
174
175   @Override
176   public CompositePackagingElement<?> getRootElement() {
177     return myLayoutTreeComponent.getRootElement();
178   }
179
180   @Override
181   public void rebuildTries() {
182     myLayoutTreeComponent.rebuildTree();
183     mySourceItemsTree.rebuildTree();
184   }
185
186   @Override
187   public void queueValidation() {
188     myContext.queueValidation();
189   }
190
191   public JComponent createMainComponent() {
192     myLayoutTreeComponent.initTree();
193     DataManager.registerDataProvider(myMainPanel, new TypeSafeDataProviderAdapter(new MyDataProvider()));
194
195     myErrorPanelPlace.add(myValidationManager.getMainErrorPanel(), BorderLayout.CENTER);
196
197     final JBSplitter splitter = new OnePixelSplitter(false);
198     final JPanel leftPanel = new JPanel(new BorderLayout());
199     JPanel treePanel = myLayoutTreeComponent.getTreePanel();
200     if (StartupUiUtil.isUnderDarcula()) {
201       treePanel.setBorder(JBUI.Borders.emptyTop(3));
202     } else {
203       treePanel.setBorder(new LineBorder(JBColor.border()));
204     }
205     leftPanel.add(treePanel, BorderLayout.CENTER);
206     if (StartupUiUtil.isUnderDarcula()) {
207       CompoundBorder border =
208         new CompoundBorder(new CustomLineBorder(0, 0, 0, 1), JBUI.Borders.empty());
209       leftPanel.setBorder(border);
210     } else {
211       leftPanel.setBorder(JBUI.Borders.empty(3, 3, 3, 0));
212     }
213     splitter.setFirstComponent(leftPanel);
214
215     final JPanel rightPanel = new JPanel(new BorderLayout());
216     final JPanel rightTopPanel = new JPanel(new BorderLayout());
217     final JPanel labelPanel = new JPanel();
218     labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.X_AXIS));
219     labelPanel.add(new JLabel(JavaUiBundle.message("label.available.elements")));
220     final HyperlinkLabel link = new HyperlinkLabel("");
221     link.setIcon(AllIcons.General.ContextHelp);
222     link.setUseIconAsLink(true);
223     link.addHyperlinkListener(new HyperlinkAdapter() {
224       @Override
225       protected void hyperlinkActivated(HyperlinkEvent e) {
226         final JLabel label = new JLabel(JavaUiBundle.message("artifact.source.items.tree.tooltip"));
227         label.setBorder(HintUtil.createHintBorder());
228         label.setBackground(HintUtil.getInformationColor());
229         label.setOpaque(true);
230         HintManager.getInstance().showHint(label, RelativePoint.getSouthWestOf(link), HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE, -1);
231       }
232     });
233     labelPanel.add(link);
234     rightTopPanel.add(labelPanel, BorderLayout.CENTER);
235     rightPanel.add(rightTopPanel, BorderLayout.NORTH);
236     JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySourceItemsTree, true);
237     JPanel scrollPaneWrap = new JPanel(new BorderLayout());
238     scrollPaneWrap.add(scrollPane, BorderLayout.CENTER);
239     if (StartupUiUtil.isUnderDarcula()) {
240       scrollPaneWrap.setBorder(JBUI.Borders.emptyTop(3));
241     } else {
242       scrollPaneWrap.setBorder(new LineBorder(JBColor.border()));
243     }
244
245     rightPanel.add(scrollPaneWrap, BorderLayout.CENTER);
246     if (StartupUiUtil.isUnderDarcula()) {
247       rightPanel.setBorder(new CompoundBorder(new CustomLineBorder(0, 1, 0, 0), JBUI.Borders.empty()));
248     } else {
249       rightPanel.setBorder(JBUI.Borders.empty(3, 0, 3, 3));
250     }
251     splitter.setSecondComponent(rightPanel);
252     splitter.getDivider().setBackground(UIUtil.getPanelBackground());
253     treePanel.setBorder(JBUI.Borders.empty());
254     rightPanel.setBorder(JBUI.Borders.empty());
255     scrollPaneWrap.setBorder(JBUI.Borders.empty());
256     leftPanel.setBorder(JBUI.Borders.empty());
257
258
259     myShowContentCheckBox.addActionListener(new ActionListener() {
260       @Override
261       public void actionPerformed(ActionEvent e) {
262         final ThreeStateCheckBox.State state = myShowContentCheckBox.getState();
263         if (state == ThreeStateCheckBox.State.SELECTED) {
264           mySubstitutionParameters.setSubstituteAll();
265         }
266         else if (state == ThreeStateCheckBox.State.NOT_SELECTED) {
267           mySubstitutionParameters.setSubstituteNone();
268         }
269         myShowContentCheckBox.setThirdStateEnabled(false);
270         myLayoutTreeComponent.rebuildTree();
271         onShowContentSettingsChanged();
272       }
273     });
274
275     ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("ProjectStructureArtifactEditor", createToolbarActionGroup(), true);
276     JComponent toolbarComponent = toolbar.getComponent();
277     if (StartupUiUtil.isUnderDarcula()) {
278       toolbarComponent.setBorder(new CustomLineBorder(0, 0, 1, 0));
279     }
280     leftPanel.add(toolbarComponent, BorderLayout.NORTH);
281     toolbar.updateActionsImmediately();
282     rightTopPanel.setPreferredSize(new Dimension(-1, toolbarComponent.getPreferredSize().height));
283
284     myTabbedPane = new TabbedPaneWrapper(this);
285     myTabbedPane.addTab(JavaUiBundle.message("tab.title.output.layout"), splitter);
286     myPropertiesEditors.addTabs(myTabbedPane);
287     myEditorPanel.add(myTabbedPane.getComponent(), BorderLayout.CENTER);
288
289     final LayoutTree tree = myLayoutTreeComponent.getLayoutTree();
290     new ShowAddPackagingElementPopupAction(this).registerCustomShortcutSet(CommonShortcuts.getNew(), tree);
291     PopupHandler.installPopupHandler(tree, createPopupActionGroup(), ActionPlaces.UNKNOWN, ActionManager.getInstance());
292     ToolTipManager.sharedInstance().registerComponent(tree);
293     rebuildTries();
294     return getMainComponent();
295   }
296
297   private void onShowContentSettingsChanged() {
298     myContext.getParent().getDefaultSettings().setTypesToShowContent(mySubstitutionParameters.getTypesToSubstitute());
299   }
300
301   public void updateShowContentCheckbox() {
302     final ThreeStateCheckBox.State state;
303     if (mySubstitutionParameters.isAllSubstituted()) {
304       state = ThreeStateCheckBox.State.SELECTED;
305     }
306     else if (mySubstitutionParameters.isNoneSubstituted()) {
307       state = ThreeStateCheckBox.State.NOT_SELECTED;
308     }
309     else {
310       state = ThreeStateCheckBox.State.DONT_CARE;
311     }
312     myShowContentCheckBox.setThirdStateEnabled(state == ThreeStateCheckBox.State.DONT_CARE);
313     myShowContentCheckBox.setState(state);
314     onShowContentSettingsChanged();
315   }
316
317   public ArtifactEditorSettings createSettings() {
318     return new ArtifactEditorSettings(myLayoutTreeComponent.isSortElements(), mySubstitutionParameters.getTypesToSubstitute());
319   }
320
321   private DefaultActionGroup createToolbarActionGroup() {
322     final DefaultActionGroup toolbarActionGroup = new DefaultActionGroup();
323
324     final List<AnAction> createActions = new ArrayList<>(createNewElementActions());
325     for (AnAction createAction : createActions) {
326       toolbarActionGroup.add(createAction);
327     }
328
329     toolbarActionGroup.add(new RemovePackagingElementAction(this));
330     toolbarActionGroup.add(Separator.getInstance());
331     toolbarActionGroup.add(new SortElementsToggleAction(this.getLayoutTreeComponent()));
332     toolbarActionGroup.add(new MovePackagingElementAction(myLayoutTreeComponent, UIBundle.message("move.up.action.name"), "", IconUtil.getMoveUpIcon(), -1));
333     toolbarActionGroup.add(new MovePackagingElementAction(myLayoutTreeComponent, UIBundle.message("move.down.action.name"), "", IconUtil.getMoveDownIcon(), 1));
334     return toolbarActionGroup;
335   }
336
337   public List<AnAction> createNewElementActions() {
338     final List<AnAction> createActions = new ArrayList<>();
339     AddCompositeElementAction.addCompositeCreateActions(createActions, this);
340     createActions.add(createAddNonCompositeElementGroup());
341     return createActions;
342   }
343
344   private DefaultActionGroup createPopupActionGroup() {
345     final LayoutTree tree = myLayoutTreeComponent.getLayoutTree();
346
347     DefaultActionGroup popupActionGroup = new DefaultActionGroup();
348     final List<AnAction> createActions = new ArrayList<>();
349     AddCompositeElementAction.addCompositeCreateActions(createActions, this);
350     for (AnAction createAction : createActions) {
351       popupActionGroup.add(createAction);
352     }
353     popupActionGroup.add(createAddNonCompositeElementGroup());
354     final RemovePackagingElementAction removeAction = new RemovePackagingElementAction(this);
355     removeAction.registerCustomShortcutSet(CommonShortcuts.getDelete(), tree);
356     popupActionGroup.add(removeAction);
357     popupActionGroup.add(new ExtractArtifactAction(this));
358     popupActionGroup.add(new InlineArtifactAction(this));
359     popupActionGroup.add(new RenamePackagingElementAction(this));
360     popupActionGroup.add(new SurroundElementWithAction(this));
361     popupActionGroup.add(Separator.getInstance());
362     popupActionGroup.add(new HideContentAction(this));
363     popupActionGroup.add(new LayoutTreeNavigateAction(myLayoutTreeComponent));
364     popupActionGroup.add(new LayoutTreeFindUsagesAction(myLayoutTreeComponent, myProject, myContext.getParent()));
365
366     popupActionGroup.add(Separator.getInstance());
367     CommonActionsManager actionsManager = CommonActionsManager.getInstance();
368     DefaultTreeExpander treeExpander = new DefaultTreeExpander(tree);
369     popupActionGroup.add(actionsManager.createExpandAllAction(treeExpander, tree));
370     popupActionGroup.add(actionsManager.createCollapseAllAction(treeExpander, tree));
371     return popupActionGroup;
372   }
373
374   @Override
375   public ComplexElementSubstitutionParameters getSubstitutionParameters() {
376     return mySubstitutionParameters;
377   }
378
379   private ActionGroup createAddNonCompositeElementGroup() {
380     DefaultActionGroup group = DefaultActionGroup.createPopupGroup(JavaUiBundle.messagePointer("artifacts.add.copy.action"));
381     group.getTemplatePresentation().setIcon(IconUtil.getAddIcon());
382     for (PackagingElementType<?> type : PackagingElementFactory.getInstance().getNonCompositeElementTypes()) {
383       group.add(new AddNewPackagingElementAction(type, this));
384     }
385     return group;
386   }
387
388   @Override
389   public JComponent getMainComponent() {
390     return myMainPanel;
391   }
392
393   @Override
394   public void addNewPackagingElement(@NotNull PackagingElementType<?> type) {
395     myLayoutTreeComponent.addNewPackagingElement(type);
396     mySourceItemsTree.rebuildTree();
397   }
398
399   @Override
400   public void removeSelectedElements() {
401     myLayoutTreeComponent.removeSelectedElements();
402   }
403
404   @Override
405   public void removePackagingElement(@NotNull final String pathToParent, @NotNull final PackagingElement<?> element) {
406     doReplaceElement(pathToParent, element, null);
407   }
408
409   @Override
410   public void replacePackagingElement(@NotNull final String pathToParent,
411                                       @NotNull final PackagingElement<?> element,
412                                       @NotNull final PackagingElement<?> replacement) {
413     doReplaceElement(pathToParent, element, replacement);
414   }
415
416   private void doReplaceElement(final @NotNull String pathToParent, final @NotNull PackagingElement<?> element, final @Nullable PackagingElement<?> replacement) {
417     myLayoutTreeComponent.editLayout(() -> {
418       final CompositePackagingElement<?> parent = findCompositeElementByPath(pathToParent);
419       if (parent == null) return;
420       for (PackagingElement<?> child : parent.getChildren()) {
421         if (child.isEqualTo(element)) {
422           parent.removeChild(child);
423           if (replacement != null) {
424             parent.addOrFindChild(replacement);
425           }
426           break;
427         }
428       }
429     });
430     myLayoutTreeComponent.rebuildTree();
431   }
432
433   @Nullable
434   private CompositePackagingElement<?> findCompositeElementByPath(String pathToElement) {
435     CompositePackagingElement<?> element = getRootElement();
436     for (String name : StringUtil.split(pathToElement, "/")) {
437       element = element.findCompositeChild(name);
438       if (element == null) return null;
439     }
440     return element;
441   }
442
443   public boolean isModified() {
444     return myBuildOnMakeCheckBox.isSelected() != myOriginalArtifact.isBuildOnMake()
445         || !Objects.equals(getConfiguredOutputPath(), myOriginalArtifact.getOutputPath())
446         || myPropertiesEditors.isModified()
447         || myLayoutTreeComponent.isPropertiesModified();
448   }
449
450   @Override
451   public void dispose() {
452     myDisposed = true;
453   }
454
455   @Override
456   public boolean isDisposed() {
457     return myDisposed;
458   }
459
460   @Override
461   public LayoutTreeComponent getLayoutTreeComponent() {
462     return myLayoutTreeComponent;
463   }
464
465   public void updateOutputPath(@NotNull String oldArtifactName, @NotNull final String newArtifactName) {
466     final String oldDefaultPath = ArtifactUtil.getDefaultArtifactOutputPath(oldArtifactName, myProject);
467     if (Objects.equals(oldDefaultPath, getConfiguredOutputPath())) {
468       setOutputPath(ArtifactUtil.getDefaultArtifactOutputPath(newArtifactName, myProject));
469     }
470     final CompositePackagingElement<?> root = getRootElement();
471     if (root instanceof ArchivePackagingElement) {
472       String oldFileName = ArtifactUtil.suggestArtifactFileName(oldArtifactName);
473       final String name = ((ArchivePackagingElement)root).getArchiveFileName();
474       final String fileName = FileUtilRt.getNameWithoutExtension(name);
475       final String extension = FileUtilRt.getExtension(name);
476       if (fileName.equals(oldFileName) && extension.length() > 0) {
477         myLayoutTreeComponent.editLayout(
478           () -> ((ArchivePackagingElement)getRootElement()).setArchiveFileName(ArtifactUtil.suggestArtifactFileName(newArtifactName) + "." + extension));
479         myLayoutTreeComponent.updateRootNode();
480       }
481     }
482     queueValidation();
483   }
484
485   @Override
486   public void updateLayoutTree() {
487     myLayoutTreeComponent.rebuildTree();
488   }
489
490   @Override
491   public void putLibraryIntoDefaultLocation(@NotNull Library library) {
492     myLayoutTreeComponent.putIntoDefaultLocations(Collections.singletonList(new LibrarySourceItem(library)));
493   }
494
495   @Override
496   public void putModuleIntoDefaultLocation(@NotNull Module module) {
497     myLayoutTreeComponent.putIntoDefaultLocations(Collections.singletonList(new ModuleOutputSourceItem(module)));
498   }
499
500   @Override
501   public void addToClasspath(final CompositePackagingElement<?> element, List<String> classpath) {
502     myLayoutTreeComponent.saveElementProperties();
503     ManifestFileConfiguration manifest = myContext.getManifestFile(element, getArtifact().getArtifactType());
504     if (manifest == null) {
505       final VirtualFile file = ManifestFileUtil.showDialogAndCreateManifest(myContext, element);
506       if (file == null) {
507         return;
508       }
509
510       ManifestFileUtil.addManifestFileToLayout(file.getPath(), myContext, element);
511       manifest = myContext.getManifestFile(element, getArtifact().getArtifactType());
512     }
513
514     if (manifest != null) {
515       manifest.addToClasspath(classpath);
516     }
517     myLayoutTreeComponent.resetElementProperties();
518   }
519
520   public void setArtifactType(ArtifactType artifactType) {
521     final ModifiableArtifact modifiableArtifact = myContext.getOrCreateModifiableArtifactModel().getOrCreateModifiableArtifact(myOriginalArtifact);
522     modifiableArtifact.setArtifactType(artifactType);
523
524     myPropertiesEditors.removeTabs(myTabbedPane);
525     myPropertiesEditors = new ArtifactPropertiesEditors(myContext, myOriginalArtifact, getArtifact());
526     myPropertiesEditors.addTabs(myTabbedPane);
527
528     final CompositePackagingElement<?> oldRootElement = getRootElement();
529     final CompositePackagingElement<?> newRootElement = artifactType.createRootElement(getArtifact().getName());
530     ArtifactUtil.copyChildren(oldRootElement, newRootElement, myProject);
531     myLayoutTreeComponent.setRootElement(newRootElement);
532   }
533
534   public ArtifactValidationManagerImpl getValidationManager() {
535     return myValidationManager;
536   }
537
538   private void createUIComponents() {
539     myShowContentCheckBox = new ThreeStateCheckBox();
540     myShowSpecificContentOptionsButton = new FixedSizeButton();
541   }
542
543   public String getHelpTopic() {
544     final int tab = myTabbedPane.getSelectedIndex();
545     if (tab == 0) {
546       return "reference.project.structure.artifacts.output";
547     }
548     String helpId = myPropertiesEditors.getHelpId(myTabbedPane.getSelectedTitle());
549     return helpId != null ? helpId : "reference.settingsdialog.project.structure.artifacts";
550   }
551
552   private class MyDataProvider implements TypeSafeDataProvider {
553     @Override
554     public void calcData(@NotNull DataKey key, @NotNull DataSink sink) {
555       if (ARTIFACTS_EDITOR_KEY.equals(key)) {
556         sink.put(ARTIFACTS_EDITOR_KEY, ArtifactEditorImpl.this);
557       }
558     }
559   }
560
561 }