blob: dd9c01a4aff845c30e1afe5ba559d9337019f4e9 [file] [log] [blame]
/*
* 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.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.ui.tree.render.CompoundNodeRenderer;
import com.intellij.debugger.ui.tree.render.NodeRenderer;
import com.intellij.ide.util.ElementsChooser;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.ui.DocumentAdapter;
import com.intellij.util.IconUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.InternalIterator;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public final class UserRenderersConfigurable extends JPanel implements ConfigurableUi<NodeRendererSettings> {
private static final Icon ADD_ICON = IconUtil.getAddIcon();
private static final Icon REMOVE_ICON = IconUtil.getRemoveIcon();
private static final Icon COPY_ICON = PlatformIcons.COPY_ICON;
private static final Icon UP_ICON = IconUtil.getMoveUpIcon();
private static final Icon DOWN_ICON = IconUtil.getMoveDownIcon();
private final JPanel myNameFieldPanel;
private final JTextField myNameField;
private final ElementsChooser<NodeRenderer> myRendererChooser;
private NodeRenderer myCurrentRenderer = null;
private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable();
public UserRenderersConfigurable() {
super(new BorderLayout(4, 0));
myRendererChooser = new ElementsChooser<NodeRenderer>(true);
setupRenderersList();
JPanel left = new JPanel(new BorderLayout());
left.add(createToolbar(), BorderLayout.NORTH);
left.add(myRendererChooser, BorderLayout.CENTER);
myNameField = new JTextField();
myNameFieldPanel = new JPanel(new BorderLayout());
myNameFieldPanel.add(new JLabel(DebuggerBundle.message("label.user.renderers.configurable.renderer.name")), BorderLayout.WEST);
myNameFieldPanel.add(myNameField, BorderLayout.CENTER);
myNameFieldPanel.setVisible(false);
final JPanel center = new JPanel(new BorderLayout(0, 4));
center.add(myNameFieldPanel, BorderLayout.NORTH);
center.add(myRendererDataConfigurable, BorderLayout.CENTER);
myNameField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
if (myCurrentRenderer != null) {
myCurrentRenderer.setName(myNameField.getText());
myRendererChooser.refresh(myCurrentRenderer);
}
}
});
add(left, BorderLayout.WEST);
add(center, BorderLayout.CENTER);
}
@Override
@NotNull
public JComponent getComponent() {
return this;
}
private void setupRenderersList() {
myRendererChooser.getEmptyText().setText(DebuggerBundle.message("text.user.renderers.configurable.no.renderers"));
myRendererChooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener<NodeRenderer>() {
@Override
public void elementMarkChanged(final NodeRenderer element, final boolean isMarked) {
element.setEnabled(isMarked);
}
});
myRendererChooser.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(@NotNull ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
updateCurrentRenderer(myRendererChooser.getSelectedElements());
}
}
});
}
private void updateCurrentRenderer(List<NodeRenderer> selectedElements) {
if (selectedElements.size() != 1) {
// multi selection
setCurrentRenderer(null);
}
else {
setCurrentRenderer(selectedElements.get(0));
}
}
private void setCurrentRenderer(NodeRenderer renderer) {
if (myCurrentRenderer == renderer) {
return;
}
if (myRendererDataConfigurable.isModified()) {
myRendererDataConfigurable.apply();
}
myCurrentRenderer = renderer;
if (renderer != null) {
myNameFieldPanel.setVisible(true);
myNameField.setText(renderer.getName());
}
else {
myNameFieldPanel.setVisible(false);
myNameField.setText("");
}
myRendererDataConfigurable.setRenderer(renderer);
}
@NotNull
private JComponent createToolbar() {
final DefaultActionGroup group = new DefaultActionGroup();
group.add(new AddAction());
group.add(new RemoveAction());
group.add(new CopyAction());
group.add(new MoveAction(true));
group.add(new MoveAction(false));
return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
}
@Override
public void apply(@NotNull NodeRendererSettings settings) {
myRendererDataConfigurable.apply();
flushTo(settings.getCustomRenderers());
settings.fireRenderersChanged();
}
private void flushTo(final RendererConfiguration rendererConfiguration) {
final int count = myRendererChooser.getElementCount();
final List<NodeRenderer> renderers = new ArrayList<NodeRenderer>(count);
for (int idx = 0; idx < count; idx++) {
renderers.add(myRendererChooser.getElementAt(idx));
}
rendererConfiguration.setRenderers(renderers);
}
@Override
public boolean isModified(@NotNull NodeRendererSettings settings) {
if (myRendererDataConfigurable.isModified()) {
return true;
}
final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
if (myRendererChooser.getElementCount() != rendererConfiguration.getRendererCount()) {
return true;
}
final RendererConfiguration uiConfiguration = new RendererConfiguration(settings);
flushTo(uiConfiguration);
return !uiConfiguration.equals(rendererConfiguration);
}
@Override
public void reset(@NotNull NodeRendererSettings settings) {
myRendererChooser.removeAllElements();
final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
final ArrayList<NodeRenderer> elementsToSelect = new ArrayList<NodeRenderer>(1);
rendererConfiguration.iterateRenderers(new InternalIterator<NodeRenderer>() {
@Override
public boolean visit(final NodeRenderer renderer) {
final NodeRenderer clonedRenderer = (NodeRenderer)renderer.clone();
myRendererChooser.addElement(clonedRenderer, clonedRenderer.isEnabled());
if (elementsToSelect.size() == 0) {
elementsToSelect.add(clonedRenderer);
}
return true;
}
});
myRendererChooser.selectElements(elementsToSelect);
updateCurrentRenderer(elementsToSelect);
myRendererDataConfigurable.reset();
}
private class AddAction extends AnAction {
public AddAction() {
super(DebuggerBundle.message("button.add"), DebuggerBundle.message("user.renderers.configurable.button.description.add"), ADD_ICON);
}
@Override
public void actionPerformed(AnActionEvent e) {
final NodeRenderer renderer = (NodeRenderer)NodeRendererSettings.getInstance().createRenderer(CompoundNodeRenderer.UNIQUE_ID);
renderer.setEnabled(true);
myRendererChooser.addElement(renderer, renderer.isEnabled());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
myNameField.requestFocus();
}
});
}
}
private class RemoveAction extends AnAction {
public RemoveAction() {
super(DebuggerBundle.message("button.remove"), DebuggerBundle.message("user.renderers.configurable.button.description.remove"), REMOVE_ICON);
}
@Override
public void actionPerformed(AnActionEvent e) {
for (NodeRenderer selectedElement : myRendererChooser.getSelectedElements()) {
myRendererChooser.removeElement(selectedElement);
}
}
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
private class CopyAction extends AnAction {
public CopyAction() {
super(DebuggerBundle.message("button.copy"), DebuggerBundle.message("user.renderers.configurable.button.description.copy"), COPY_ICON);
}
@Override
public void actionPerformed(AnActionEvent e) {
final NodeRenderer selectedElement = myRendererChooser.getSelectedElement();
if (selectedElement != null) {
myRendererChooser.addElement((NodeRenderer)selectedElement.clone(), true);
}
}
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
private class MoveAction extends AnAction {
private final boolean myMoveUp;
public MoveAction(boolean up) {
super(up? DebuggerBundle.message("button.move.up") : DebuggerBundle.message("button.move.down"),
up? DebuggerBundle.message("user.renderers.configurable.button.description.move.up") : DebuggerBundle.message("user.renderers.configurable.button.description.move.down"),
up? UP_ICON : DOWN_ICON );
myMoveUp = up;
}
@Override
public void actionPerformed(AnActionEvent e) {
final int selectedRow = myRendererChooser.getSelectedElementRow();
if (selectedRow < 0) {
return;
}
int newRow = selectedRow + (myMoveUp? -1 : 1);
if (newRow < 0) {
newRow = myRendererChooser.getElementCount() - 1;
}
else if (newRow >= myRendererChooser.getElementCount()) {
newRow = 0;
}
myRendererChooser.moveElement(myRendererChooser.getElementAt(selectedRow), newRow);
}
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
}