diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java deleted file mode 100644 index a2481e0f19ef..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.intellij.openapi.actionSystem; - -import com.intellij.openapi.project.DumbAware; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class ComputableActionGroup extends ActionGroup implements DumbAware { - private AnAction[] myChildren; - - protected ComputableActionGroup() { - } - - protected ComputableActionGroup(boolean popup) { - super(null, popup); - } - - @Override - public boolean hideIfNoVisibleChildren() { - return true; - } - - @Override - @NotNull - public final AnAction[] getChildren(@Nullable AnActionEvent e) { - if (e == null) { - return EMPTY_ARRAY; - } - - if (myChildren == null) { - myChildren = computeChildren(e.getActionManager()); - } - return myChildren; - } - - @NotNull - protected abstract AnAction[] computeChildren(@NotNull ActionManager manager); -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java new file mode 100644 index 000000000000..b5027fd9df81 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2014 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.openapi.actionSystem; + +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.ModificationTracker; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.util.CachedValueImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class ComputableActionGroup extends ActionGroup implements DumbAware { + private CachedValue myChildren; + + protected ComputableActionGroup() { + } + + protected ComputableActionGroup(boolean popup) { + super(null, popup); + } + + @Override + public boolean hideIfNoVisibleChildren() { + return true; + } + + @Override + @NotNull + public final AnAction[] getChildren(@Nullable AnActionEvent e) { + if (e == null) { + return EMPTY_ARRAY; + } + + if (myChildren == null) { + myChildren = new CachedValueImpl(createChildrenProvider(e.getActionManager())); + } + return myChildren.getValue(); + } + + @NotNull + protected abstract CachedValueProvider createChildrenProvider(@NotNull ActionManager actionManager); + + public abstract static class Simple extends ComputableActionGroup { + @NotNull + @Override + protected final CachedValueProvider createChildrenProvider(@NotNull final ActionManager actionManager) { + return new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + return Result.create(computeChildren(actionManager), ModificationTracker.NEVER_CHANGED); + } + }; + } + + @NotNull + protected abstract AnAction[] computeChildren(@NotNull ActionManager manager); + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java b/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java index 1955a1826ffa..92985f2fd571 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java +++ b/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java @@ -49,6 +49,10 @@ public class LocalPathCellEditor extends AbstractTableCellEditor { this(null, project); } + public LocalPathCellEditor() { + this(null, null); + } + public LocalPathCellEditor fileChooserDescriptor(@NotNull FileChooserDescriptor fileChooserDescriptor) { myFileChooserDescriptor = fileChooserDescriptor; return this; diff --git a/platform/util/src/com/intellij/util/ui/ColumnInfo.java b/platform/util/src/com/intellij/util/ui/ColumnInfo.java index 480980e96561..8289633b111d 100644 --- a/platform/util/src/com/intellij/util/ui/ColumnInfo.java +++ b/platform/util/src/com/intellij/util/ui/ColumnInfo.java @@ -96,7 +96,7 @@ public abstract class ColumnInfo { /** * @see com.intellij.util.ui.table.ComboBoxTableCellEditor */ - public TableCellEditor getEditor(Item o) { + public TableCellEditor getEditor(Item item) { return null; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java index ea89d7974ec2..926e5cced906 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java @@ -18,17 +18,16 @@ package com.intellij.openapi.vcs.checkout; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.ComputableActionGroup; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.vcs.CheckoutProvider; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -public class CheckoutActionGroup extends ComputableActionGroup { +public class CheckoutActionGroup extends ComputableActionGroup.Simple { @NotNull @Override protected AnAction[] computeChildren(@NotNull ActionManager manager) { - CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME); + CheckoutProvider[] providers = CheckoutProvider.EXTENSION_POINT_NAME.getExtensions(); if (providers.length == 0) { return EMPTY_ARRAY; } diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java index c650361c7f89..7860a80bd712 100644 --- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java +++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java @@ -27,17 +27,11 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.TableSpeedSearch; -import com.intellij.ui.TableUtil; -import com.intellij.ui.ToolbarDecorator; -import com.intellij.ui.table.TableView; +import com.intellij.util.Function; import com.intellij.util.ui.ColumnInfo; -import com.intellij.util.ui.ListTableModel; import com.intellij.util.ui.LocalPathCellEditor; import com.intellij.util.ui.table.ComboBoxTableCellEditor; import com.intellij.util.ui.table.IconTableCellRenderer; -import gnu.trove.THashMap; -import gnu.trove.TObjectObjectProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,10 +40,9 @@ import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Map; import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; +import static com.intellij.ide.browsers.TableModelEditor.EditableColumnInfo; public class BrowserSettingsPanel { private JPanel root; @@ -66,7 +59,8 @@ public class BrowserSettingsPanel { @SuppressWarnings("UnusedDeclaration") private JComponent browsersTable; - private final THashMap modifiedBrowsers = new THashMap(); + private TableModelEditor browsersEditor; + private final FileChooserDescriptor appFileChooserDescriptor; public BrowserSettingsPanel() { @@ -105,125 +99,91 @@ public class BrowserSettingsPanel { }); } - private ConfigurableWebBrowser getEffective(ConfigurableWebBrowser info) { - ConfigurableWebBrowser mutable = modifiedBrowsers.isEmpty() ? null : modifiedBrowsers.get(info); - return mutable == null ? info : mutable; - } - - private ConfigurableWebBrowser getMutable(ConfigurableWebBrowser info) { - ConfigurableWebBrowser mutable = modifiedBrowsers.get(info); - if (mutable == null) { - mutable = new ConfigurableWebBrowser(info.getId(), info.getFamily(), info.getName(), info.getPath(), info.isActive(), info.getSpecificSettings()); - modifiedBrowsers.put(info, mutable); - } - return mutable; - } - private void createUIComponents() { - ColumnInfo[] columns = {new ColumnInfo("") { + browsersEditor = new TableModelEditor(WebBrowserManager.getInstance().getList(), new ColumnInfo[]{new EditableColumnInfo() { @Override public Class getColumnClass() { return Boolean.class; } @Override - public Boolean valueOf(ConfigurableWebBrowser info) { - return getEffective(info).isActive(); + public Boolean valueOf(ConfigurableWebBrowser item) { + return browsersEditor.getEffective(item).isActive(); } @Override - public boolean isCellEditable(ConfigurableWebBrowser info) { - return true; - } - - @Override - public void setValue(ConfigurableWebBrowser info, Boolean value) { - if (value != info.isActive()) { - getMutable(info).setActive(value); + public void setValue(ConfigurableWebBrowser item, Boolean value) { + if (value != item.isActive()) { + browsersEditor.getMutable(item).setActive(value); } } - }, new ColumnInfo("Name") { + }, new EditableColumnInfo("Name") { @Override - public String valueOf(ConfigurableWebBrowser info) { - return getEffective(info).getName(); + public String valueOf(ConfigurableWebBrowser item) { + return browsersEditor.getEffective(item).getName(); } @Override - public boolean isCellEditable(ConfigurableWebBrowser info) { - return true; - } - - @Override - public void setValue(ConfigurableWebBrowser info, String value) { - if (!value.equals(info.getName())) { - getMutable(info).setName(value); + public void setValue(ConfigurableWebBrowser item, String value) { + if (!value.equals(item.getName())) { + browsersEditor.getMutable(item).setName(value); } } - }, new ColumnInfo("Family") { + }, new EditableColumnInfo("Family") { @Override public Class getColumnClass() { return BrowserFamily.class; } @Override - public BrowserFamily valueOf(ConfigurableWebBrowser info) { - return getEffective(info).getFamily(); + public BrowserFamily valueOf(ConfigurableWebBrowser item) { + return browsersEditor.getEffective(item).getFamily(); } @Override - public boolean isCellEditable(ConfigurableWebBrowser info) { - return true; - } - - @Override - public void setValue(ConfigurableWebBrowser info, BrowserFamily value) { - if (value != info.getFamily()) { - getMutable(info).setFamily(value); + public void setValue(ConfigurableWebBrowser item, BrowserFamily value) { + if (value != item.getFamily()) { + browsersEditor.getMutable(item).setFamily(value); } } @Nullable @Override - public TableCellRenderer getRenderer(ConfigurableWebBrowser info) { + public TableCellRenderer getRenderer(ConfigurableWebBrowser item) { return IconTableCellRenderer.ICONABLE; } @Nullable @Override - public TableCellEditor getEditor(ConfigurableWebBrowser o) { + public TableCellEditor getEditor(ConfigurableWebBrowser item) { return ComboBoxTableCellEditor.INSTANCE; } - }, new ColumnInfo("Path") { + }, new EditableColumnInfo("Path") { @Override public String valueOf(ConfigurableWebBrowser info) { - return getEffective(info).getPath(); + return browsersEditor.getEffective(info).getPath(); } @Override - public boolean isCellEditable(ConfigurableWebBrowser info) { - return true; - } - - @Override - public void setValue(ConfigurableWebBrowser info, String value) { - if (!value.equals(info.getPath())) { - getMutable(info).setPath(StringUtil.nullize(value, true)); + public void setValue(ConfigurableWebBrowser item, String value) { + String normalizedValue = StringUtil.nullize(value, true); + if (!Comparing.equal(normalizedValue, item.getPath())) { + browsersEditor.getMutable(item).setPath(normalizedValue); } } @Nullable @Override - public TableCellEditor getEditor(ConfigurableWebBrowser info) { - return new LocalPathCellEditor(null).fileChooserDescriptor(appFileChooserDescriptor); + public TableCellEditor getEditor(ConfigurableWebBrowser item) { + return new LocalPathCellEditor().fileChooserDescriptor(appFileChooserDescriptor); } - }}; - ListTableModel tableModel = new ListTableModel(columns, new ArrayList(WebBrowserManager.getInstance().getList())); - TableView table = new TableView(tableModel); - table.setStriped(true); - new TableSpeedSearch(table); - TableUtil.setupCheckboxColumn(table.getColumnModel().getColumn(0)); - - browsersTable = ToolbarDecorator.createDecorator(table).createPanel(); + }}, new Function() { + @Override + public ConfigurableWebBrowser fun(ConfigurableWebBrowser browser) { + return new ConfigurableWebBrowser(browser.getId(), browser.getFamily(), browser.getName(), browser.getPath(), browser.isActive(), browser.getSpecificSettings()); + } + }, ConfigurableWebBrowser.class); + browsersTable = browsersEditor.createComponent(); } @NotNull @@ -233,23 +193,13 @@ public class BrowserSettingsPanel { public boolean isModified() { GeneralSettings settings = GeneralSettings.getInstance(); - boolean isModified = !Comparing.strEqual(settings.getBrowserPath(), alternativeBrowserPathField.getText()); - isModified |= settings.isUseDefaultBrowser() != useSystemDefaultBrowser.isSelected(); - isModified |= settings.isConfirmExtractFiles() != confirmExtractFiles.isSelected(); - - if (isModified) { + if (!Comparing.strEqual(settings.getBrowserPath(), alternativeBrowserPathField.getText()) || + settings.isUseDefaultBrowser() != useSystemDefaultBrowser.isSelected() || + settings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) { return true; } - if (!modifiedBrowsers.isEmpty()) { - for (Map.Entry entry : modifiedBrowsers.entrySet()) { - if (entry.getValue().isChanged(entry.getKey())) { - return true; - } - } - } - - return false; + return browsersEditor.isModified(WebBrowserManager.getInstance().getList()); } private void updateBrowserField() { @@ -268,19 +218,7 @@ public class BrowserSettingsPanel { settings.setUseDefaultBrowser(useSystemDefaultBrowser.isSelected()); settings.setConfirmExtractFiles(confirmExtractFiles.isSelected()); - if (!modifiedBrowsers.isEmpty()) { - modifiedBrowsers.forEachEntry(new TObjectObjectProcedure() { - @Override - public boolean execute(ConfigurableWebBrowser info, ConfigurableWebBrowser newInfo) { - info.setName(newInfo.getName()); - info.setFamily(newInfo.getFamily()); - info.setPath(newInfo.getPath()); - info.setActive(newInfo.isActive()); - info.setSpecificSettings(newInfo.getSpecificSettings()); - return true; - } - }); - } + WebBrowserManager.getInstance().setList(browsersEditor.apply()); } public void reset() { @@ -297,7 +235,7 @@ public class BrowserSettingsPanel { updateBrowserField(); - modifiedBrowsers.clear(); + browsersEditor.clear(); } public void disposeUIResources() { diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java index 495e62360b96..b191d188127d 100644 --- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java +++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java @@ -1,5 +1,6 @@ package com.intellij.ide.browsers; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -7,6 +8,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.UUID; +import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; + final class ConfigurableWebBrowser extends WebBrowser { private boolean active; private final UUID id; @@ -14,12 +17,17 @@ final class ConfigurableWebBrowser extends WebBrowser { private BrowserSpecificSettings specificSettings; - public ConfigurableWebBrowser(@NotNull UUID id, @NotNull BrowsersConfiguration.BrowserFamily family) { + @SuppressWarnings("UnusedDeclaration") + public ConfigurableWebBrowser() { + this(UUID.randomUUID(), BrowserFamily.CHROME); + } + + public ConfigurableWebBrowser(@NotNull UUID id, @NotNull BrowserFamily family) { this(id, family, family.getName(), family.getExecutionPath(), true, family.createBrowserSpecificSettings()); } public ConfigurableWebBrowser(@NotNull UUID id, - @NotNull BrowsersConfiguration.BrowserFamily family, + @NotNull BrowserFamily family, @NotNull String name, @Nullable String path, boolean active, @@ -36,7 +44,7 @@ final class ConfigurableWebBrowser extends WebBrowser { name = value; } - public void setFamily(@NotNull BrowsersConfiguration.BrowserFamily value) { + public void setFamily(@NotNull BrowserFamily value) { family = value; } @@ -83,4 +91,25 @@ final class ConfigurableWebBrowser extends WebBrowser { public boolean isChanged(@NotNull ConfigurableWebBrowser info) { return active != info.active || family != info.family || !StringUtil.equals(name, info.name) || !StringUtil.equals(path, info.path); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ConfigurableWebBrowser)) { + return false; + } + + ConfigurableWebBrowser browser = (ConfigurableWebBrowser)o; + return id.equals(browser.id) && + active == browser.active && + Comparing.equal(path, browser.path) && + Comparing.equal(specificSettings, browser.specificSettings); + } + + @Override + public int hashCode() { + return id.hashCode(); + } } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java index cf47177938f9..640bbcd972d0 100644 --- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java +++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java @@ -36,7 +36,7 @@ public class StartBrowserSettings { } @Nullable - @Attribute("url") + @Attribute public String getUrl() { return myUrl; } diff --git a/xml/impl/src/com/intellij/ide/browsers/TableModelEditor.java b/xml/impl/src/com/intellij/ide/browsers/TableModelEditor.java new file mode 100644 index 000000000000..a3ea1f779b9b --- /dev/null +++ b/xml/impl/src/com/intellij/ide/browsers/TableModelEditor.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2014 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.ide.browsers; + +import com.intellij.ui.TableSpeedSearch; +import com.intellij.ui.TableUtil; +import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.table.TableView; +import com.intellij.util.Function; +import com.intellij.util.ui.ColumnInfo; +import com.intellij.util.ui.ElementProducer; +import com.intellij.util.ui.ListTableModel; +import gnu.trove.THashMap; +import gnu.trove.TObjectObjectProcedure; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TableModelEditor implements ElementProducer { + private final List items; + private final TableView table; + + private final THashMap modifiedItems = new THashMap(); + private final Function mutableFactory; + private final Class itemClass; + + private boolean isApplying; + + /** + * source will be copied, passed list will not be used directly + * itemClass must has empty constructor + */ + public TableModelEditor(@NotNull List source, @NotNull ColumnInfo[] columns, @NotNull Function mutableFactory, Class itemClass) { + this.itemClass = itemClass; + items = new ArrayList(source); + this.mutableFactory = mutableFactory; + + table = new TableView(new ListTableModel(columns, items)); + table.setStriped(true); + new TableSpeedSearch(table); + if (columns[0].getColumnClass() == Boolean.class && columns[0].getName().isEmpty()) { + TableUtil.setupCheckboxColumn(table.getColumnModel().getColumn(0)); + } + } + + public abstract static class EditableColumnInfo extends ColumnInfo { + public EditableColumnInfo(@NotNull String name) { + super(name); + } + + public EditableColumnInfo() { + super(""); + } + + @Override + public boolean isCellEditable(Item item) { + return true; + } + } + + @NotNull + public JComponent createComponent() { + return ToolbarDecorator.createDecorator(table, this).createPanel(); + } + + @Override + public T createElement() { + try { + return itemClass.newInstance(); + } + catch (InstantiationException e) { + throw new RuntimeException(e); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean canCreateElement() { + return true; + } + + @NotNull + public T getEffective(@NotNull T item) { + T mutable = isApplying || modifiedItems.isEmpty() ? null : modifiedItems.get(item); + return mutable == null ? item : mutable; + } + + @NotNull + public T getMutable(@NotNull T item) { + if (isApplying) { + return item; + } + + T mutable = modifiedItems.get(item); + if (mutable == null) { + mutable = mutableFactory.fun(item); + modifiedItems.put(item, mutable); + } + return mutable; + } + + public boolean isModified(@NotNull List oldItems) { + if (!modifiedItems.isEmpty()) { + for (Map.Entry entry : modifiedItems.entrySet()) { + if (entry.getValue().equals(entry.getKey())) { + return true; + } + } + } + + // is order changed or new items added? + if (items.size() == oldItems.size()) { + for (int i = 0, size = items.size(); i < size; i++) { + if (items.get(i) != oldItems.get(i)) { + return true; + } + } + } + else { + return true; + } + + return false; + } + + @NotNull + public List apply() { + if (!modifiedItems.isEmpty()) { + isApplying = true; + + @SuppressWarnings("unchecked") + final ColumnInfo[] columns = ((ListTableModel)table.getModel()).getColumnInfos(); + modifiedItems.forEachEntry(new TObjectObjectProcedure() { + @Override + public boolean execute(T item, T newItem) { + for (ColumnInfo column : columns) { + if (column.isCellEditable(item)) { + column.setValue(item, column.valueOf(newItem)); + } + } + return true; + } + }); + + isApplying = false; + modifiedItems.clear(); + } + return items; + } + + public void clear() { + modifiedItems.clear(); + } +} \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java index 59a6a006416a..46807330021c 100644 --- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java +++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java @@ -17,6 +17,7 @@ package com.intellij.ide.browsers; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SmartList; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; @@ -33,7 +34,7 @@ import java.util.UUID; import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily; @State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/browsers.xml")}) -public class WebBrowserManager implements PersistentStateComponent { +public class WebBrowserManager implements PersistentStateComponent, ModificationTracker { private static final Logger LOG = Logger.getInstance(WebBrowserManager.class); // default standard browser ID must be constant across all IDE versions on all machines for all users @@ -43,7 +44,9 @@ public class WebBrowserManager implements PersistentStateComponent { private static final UUID DEFAULT_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776"); private static final UUID DEFAULT_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0"); - private final List browsers; + private List browsers; + + private long modificationCount; public WebBrowserManager() { browsers = new ArrayList(); @@ -182,8 +185,7 @@ public class WebBrowserManager implements PersistentStateComponent { specificSettings)); } - browsers.clear(); - browsers.addAll(list); + setList(list); } @NotNull @@ -196,6 +198,11 @@ public class WebBrowserManager implements PersistentStateComponent { return browsers; } + void setList(@NotNull List value) { + browsers = value; + modificationCount++; + } + @NotNull public List getActiveBrowsers() { List result = new SmartList(); @@ -257,4 +264,9 @@ public class WebBrowserManager implements PersistentStateComponent { public boolean isActive(@NotNull WebBrowser browser) { return !(browser instanceof ConfigurableWebBrowser) || ((ConfigurableWebBrowser)browser).isActive(); } + + @Override + public long getModificationCount() { + return modificationCount; + } } \ No newline at end of file diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java index 751eb51ba7ea..cf5e9553b110 100644 --- a/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java +++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2014 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.ide.browsers.actions; import com.intellij.icons.AllIcons; @@ -6,9 +21,11 @@ import com.intellij.ide.browsers.WebBrowserManager; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.ComputableActionGroup; +import com.intellij.psi.util.CachedValueProvider; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -21,33 +38,39 @@ public abstract class OpenInBrowserBaseGroupAction extends ComputableActionGroup @NotNull @Override - protected AnAction[] computeChildren(@NotNull ActionManager manager) { - List actionsByEP = new SmartList(); - for (OpenInBrowserActionProducer actionProducer : OpenInBrowserActionProducer.EP_NAME.getExtensions()) { - actionsByEP.addAll(actionProducer.getActions()); - } + protected final CachedValueProvider createChildrenProvider(@NotNull final ActionManager actionManager) { + return new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + List actionsByEP = new SmartList(); + for (OpenInBrowserActionProducer actionProducer : OpenInBrowserActionProducer.EP_NAME.getExtensions()) { + actionsByEP.addAll(actionProducer.getActions()); + } - List browsers = WebBrowserManager.getInstance().getBrowsers(); - boolean addDefaultBrowser = isPopup(); - int offset = addDefaultBrowser ? 1 : 0; - AnAction[] actions = new AnAction[browsers.size() + offset + actionsByEP.size()]; + List browsers = WebBrowserManager.getInstance().getBrowsers(); + boolean addDefaultBrowser = isPopup(); + int offset = addDefaultBrowser ? 1 : 0; + AnAction[] actions = new AnAction[browsers.size() + offset + actionsByEP.size()]; - if (addDefaultBrowser) { - if (myDefaultBrowserAction == null) { - myDefaultBrowserAction = new OpenFileInDefaultBrowserAction(); - myDefaultBrowserAction.getTemplatePresentation().setText("Default"); - myDefaultBrowserAction.getTemplatePresentation().setIcon(AllIcons.Nodes.PpWeb); + if (addDefaultBrowser) { + if (myDefaultBrowserAction == null) { + myDefaultBrowserAction = new OpenFileInDefaultBrowserAction(); + myDefaultBrowserAction.getTemplatePresentation().setText("Default"); + myDefaultBrowserAction.getTemplatePresentation().setIcon(AllIcons.Nodes.PpWeb); + } + actions[0] = myDefaultBrowserAction; + } + + for (int i = 0, size = browsers.size(); i < size; i++) { + actions[i + offset] = new BaseWebBrowserAction(browsers.get(i)); + } + + ArrayUtil.copy(actionsByEP, actions, offset + browsers.size()); + + return Result.create(actions, WebBrowserManager.getInstance()); } - actions[0] = myDefaultBrowserAction; - } - - for (int i = 0, size = browsers.size(); i < size; i++) { - actions[i + offset] = new BaseWebBrowserAction(browsers.get(i)); - } - - ArrayUtil.copy(actionsByEP, actions, offset + browsers.size()); - - return actions; + }; } public static final class OpenInBrowserGroupAction extends OpenInBrowserBaseGroupAction {