package com.intellij.lang.javascript.flex.projectStructure.ui; import com.intellij.lang.javascript.flex.FlexBundle; import com.intellij.lang.javascript.flex.FlexUtils; import com.intellij.lang.javascript.flex.projectStructure.model.*; import com.intellij.openapi.Disposable; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.NamedConfigurable; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.UserActivityListener; import com.intellij.ui.UserActivityWatcher; import com.intellij.ui.navigation.History; import com.intellij.ui.navigation.Place; import com.intellij.util.EventDispatcher; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public abstract class AirPackagingConfigurableBase<T extends ModifiableAirPackagingOptions> extends NamedConfigurable<T> implements Place.Navigator { public enum Location { CustomDescriptor("custom-descriptor-path"), PackageFileName("package-file-name"), FilesToPackage("files-to-package"), ProvisioningProfile("provisioning-profile"), Keystore("keystore"), IosSdkPath("ios-sdk-path"); public final String errorId; Location(final String errorId) { this.errorId = errorId; } } public interface AirDescriptorInfoProvider { String getMainClass(); String getAirVersion(); String[] getExtensionIDs(); boolean isAndroidPackagingEnabled(); boolean isIOSPackagingEnabled(); void setCustomDescriptorForAndroidAndIOS(String descriptorPath); } private JPanel myMainPanel; private JCheckBox myEnabledCheckBox; private AirDescriptorForm myAirDescriptorForm; private JTextField myPackageFileNameTextField; private FilesToPackageForm myFilesToPackageForm; private SigningOptionsForm mySigningOptionsForm; private final Module myModule; private final T myModel; private final boolean isAndroid; private final boolean isIOS; private final AirDescriptorInfoProvider myAirDescriptorInfoProvider; private final Disposable myDisposable; private final EventDispatcher<UserActivityListener> myUserActivityDispatcher; private boolean myFreeze; public AirPackagingConfigurableBase(final Module module, final T model, final AirDescriptorInfoProvider airDescriptorInfoProvider) { myModule = module; myModel = model; myAirDescriptorInfoProvider = airDescriptorInfoProvider; isAndroid = model instanceof ModifiableAndroidPackagingOptions; isIOS = model instanceof ModifiableIosPackagingOptions; myEnabledCheckBox.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { updateControls(); } }); myDisposable = Disposer.newDisposable(); UserActivityWatcher watcher = new UserActivityWatcher(); watcher.register(myMainPanel); myUserActivityDispatcher = EventDispatcher.create(UserActivityListener.class); watcher.addUserActivityListener(new UserActivityListener() { @Override public void stateChanged() { if (myFreeze) { return; } myUserActivityDispatcher.getMulticaster().stateChanged(); } }, myDisposable); } public void addUserActivityListener(final UserActivityListener listener, final Disposable disposable) { myUserActivityDispatcher.addListener(listener, disposable); } public void removeUserActivityListeners() { for (UserActivityListener listener : myUserActivityDispatcher.getListeners()) { myUserActivityDispatcher.removeListener(listener); } } private void updateControls() { final boolean enabled = isPackagingEnabled(); UIUtil.setEnabled(myMainPanel, enabled, true); myEnabledCheckBox.setEnabled(true); myAirDescriptorForm.updateControls(); mySigningOptionsForm.setEnabled(enabled); } public T getEditableObject() { return myModel; } public void setDisplayName(final String name) { } public String getBannerSlogan() { return getDisplayName(); } public JComponent createOptionsPanel() { return myMainPanel; } public void reset() { myFreeze = true; try { myEnabledCheckBox.setVisible(isAndroid || isIOS); if (isAndroid) myEnabledCheckBox.setSelected(((AndroidPackagingOptions)myModel).isEnabled()); if (isIOS) myEnabledCheckBox.setSelected(((IosPackagingOptions)myModel).isEnabled()); myAirDescriptorForm.resetFrom(myModel); myPackageFileNameTextField.setText(myModel.getPackageFileName()); myFilesToPackageForm.resetFrom(myModel.getFilesToPackage()); mySigningOptionsForm.resetFrom(myModel.getSigningOptions()); updateControls(); } finally { myFreeze = false; } } public boolean isModified() { if (isAndroid && myEnabledCheckBox.isSelected() != ((AndroidPackagingOptions)myModel).isEnabled()) return true; if (isIOS && myEnabledCheckBox.isSelected() != ((IosPackagingOptions)myModel).isEnabled()) return true; if (myAirDescriptorForm.isModified(myModel)) return true; if (!myModel.getPackageFileName().equals(myPackageFileNameTextField.getText().trim())) return true; if (myFilesToPackageForm.isModified(myModel.getFilesToPackage())) return true; if (mySigningOptionsForm.isModified(myModel.getSigningOptions())) return true; return false; } public void apply() throws ConfigurationException { applyTo(myModel); } public void applyTo(final ModifiableAirPackagingOptions model) { if (isAndroid) ((ModifiableAndroidPackagingOptions)model).setEnabled(myEnabledCheckBox.isSelected()); if (isIOS) ((ModifiableIosPackagingOptions)model).setEnabled(myEnabledCheckBox.isSelected()); myAirDescriptorForm.applyTo(model); model.setPackageFileName(myPackageFileNameTextField.getText().trim()); model.setFilesToPackage(myFilesToPackageForm.getFilesToPackage()); mySigningOptionsForm.applyTo(model.getSigningOptions()); } public void disposeUIResources() { Disposer.dispose(myDisposable); } private void createUIComponents() { final Runnable descriptorCreator = () -> { final String folderPath = FlexUtils.getContentOrModuleFolderPath(myModule); final String mainClass = myAirDescriptorInfoProvider.getMainClass(); final String airVersion = myAirDescriptorInfoProvider.getAirVersion(); final String[] extensions = myAirDescriptorInfoProvider.getExtensionIDs(); final boolean androidEnabled = myAirDescriptorInfoProvider.isAndroidPackagingEnabled(); final boolean iosEnabled = myAirDescriptorInfoProvider.isIOSPackagingEnabled(); final CreateAirDescriptorTemplateDialog dialog = new CreateAirDescriptorTemplateDialog(myModule.getProject(), folderPath, mainClass, airVersion, extensions, androidEnabled, iosEnabled); if (dialog.showAndGet()) { final String descriptorPath = dialog.getDescriptorPath(); setUseCustomDescriptor(descriptorPath); if (androidEnabled && iosEnabled && dialog.isBothAndroidAndIosSelected()) { final int choice = Messages.showYesNoDialog(myModule.getProject(), FlexBundle.message("use.same.descriptor.for.android.and.ios"), CreateAirDescriptorTemplateDialog.TITLE, Messages.getQuestionIcon()); if (choice == Messages.YES) { myAirDescriptorInfoProvider.setCustomDescriptorForAndroidAndIOS(descriptorPath); } } } }; myAirDescriptorForm = new AirDescriptorForm(myModule.getProject(), descriptorCreator); myFilesToPackageForm = new FilesToPackageForm(myModule.getProject()); final SigningOptionsForm.Mode mode = isIOS ? SigningOptionsForm.Mode.iOS : isAndroid ? SigningOptionsForm.Mode.Android : SigningOptionsForm.Mode.Desktop; mySigningOptionsForm = new SigningOptionsForm(myModule.getProject(), mode); } public void setUseCustomDescriptor(final String descriptorPath) { myAirDescriptorForm.setUseCustomDescriptor(descriptorPath); } public boolean isPackagingEnabled() { return !myEnabledCheckBox.isVisible() || myEnabledCheckBox.isSelected(); } public void setHistory(final History history) { } public ActionCallback navigateTo(@Nullable final Place place, final boolean requestFocus) { if (place != null) { final Object location = place.getPath(FlexBCConfigurable.LOCATION_ON_TAB); if (location instanceof Location) { switch ((Location)location) { case CustomDescriptor: return myAirDescriptorForm.navigateTo((Location)location); case PackageFileName: return IdeFocusManager.findInstance().requestFocus(myPackageFileNameTextField, true); case FilesToPackage: return myFilesToPackageForm.navigateTo((Location)location); case ProvisioningProfile: case Keystore: case IosSdkPath: return mySigningOptionsForm.navigateTo((Location)location); } } } return ActionCallback.DONE; } public void queryPlace(@NotNull final Place place) { } }