| /* |
| * 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.commander; |
| |
| import com.intellij.history.LocalHistory; |
| import com.intellij.history.LocalHistoryAction; |
| import com.intellij.ide.CopyPasteDelegator; |
| import com.intellij.ide.DeleteProvider; |
| import com.intellij.ide.IdeBundle; |
| import com.intellij.ide.IdeView; |
| import com.intellij.ide.projectView.ProjectViewNode; |
| import com.intellij.ide.projectView.impl.ModuleGroup; |
| import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase; |
| import com.intellij.ide.projectView.impl.nodes.LibraryGroupElement; |
| import com.intellij.ide.projectView.impl.nodes.NamedLibraryElement; |
| import com.intellij.ide.structureView.StructureViewTreeElement; |
| import com.intellij.ide.ui.customization.CustomActionsSchema; |
| import com.intellij.ide.util.DeleteHandler; |
| import com.intellij.ide.util.DirectoryChooserUtil; |
| import com.intellij.ide.util.EditSourceUtil; |
| import com.intellij.ide.util.EditorHelper; |
| import com.intellij.ide.util.treeView.AbstractTreeNode; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.application.ModalityState; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.SystemInfo; |
| import com.intellij.openapi.wm.ToolWindowManager; |
| import com.intellij.pom.Navigatable; |
| import com.intellij.psi.PsiDirectory; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.util.PsiUtilCore; |
| import com.intellij.ui.*; |
| import com.intellij.ui.components.JBList; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.border.BevelBorder; |
| import java.awt.*; |
| import java.awt.event.*; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * @author Eugene Belyaev |
| */ |
| public class CommanderPanel extends JPanel { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.ide.commander.CommanderPanel"); |
| |
| private static final Color DARK_BLUE = new Color(55, 85, 134); |
| private static final Color DARK_BLUE_BRIGHTER = new Color(58, 92, 149); |
| private static final Color DARK_BLUE_DARKER = new Color(38, 64, 106); |
| |
| private Project myProject; |
| private AbstractListBuilder myBuilder; |
| private JPanel myTitlePanel; |
| private JLabel myParentTitle; |
| protected final JBList myList; |
| private final MyModel myModel; |
| |
| private CopyPasteDelegator myCopyPasteDelegator; |
| protected final ListSpeedSearch myListSpeedSearch; |
| private final IdeView myIdeView = new MyIdeView(); |
| private final MyDeleteElementProvider myDeleteElementProvider = new MyDeleteElementProvider(); |
| @NonNls |
| private static final String ACTION_DRILL_DOWN = "DrillDown"; |
| @NonNls |
| private static final String ACTION_GO_UP = "GoUp"; |
| private ProjectAbstractTreeStructureBase myProjectTreeStructure; |
| private boolean myActive = true; |
| private final List<CommanderHistoryListener> myHistoryListeners = ContainerUtil.createLockFreeCopyOnWriteList(); |
| private boolean myMoveFocus = false; |
| private final boolean myEnableSearchHighlighting; |
| |
| public CommanderPanel(final Project project, final boolean enablePopupMenu, final boolean enableSearchHighlighting) { |
| super(new BorderLayout()); |
| myProject = project; |
| myEnableSearchHighlighting = enableSearchHighlighting; |
| myModel = new MyModel(); |
| myList = new JBList(myModel); |
| myList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); |
| |
| if (enablePopupMenu) { |
| myCopyPasteDelegator = new CopyPasteDelegator(myProject, myList) { |
| @Override |
| @NotNull |
| protected PsiElement[] getSelectedElements() { |
| return CommanderPanel.this.getSelectedElements(); |
| } |
| }; |
| } |
| |
| myListSpeedSearch = new ListSpeedSearch(myList); |
| myListSpeedSearch.setClearSearchOnNavigateNoMatch(true); |
| |
| ListScrollingUtil.installActions(myList); |
| |
| myList.registerKeyboardAction(new ActionListener() { |
| @Override |
| public void actionPerformed(final ActionEvent e) { |
| if (myBuilder == null) return; |
| myBuilder.buildRoot(); |
| } |
| }, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SLASH, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK), |
| JComponent.WHEN_FOCUSED); |
| |
| myList.getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ACTION_DRILL_DOWN); |
| myList.getInputMap(WHEN_FOCUSED) |
| .put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK), |
| ACTION_DRILL_DOWN); |
| myList.getActionMap().put(ACTION_DRILL_DOWN, new AbstractAction() { |
| @Override |
| public void actionPerformed(final ActionEvent e) { |
| drillDown(); |
| } |
| }); |
| new DoubleClickListener() { |
| @Override |
| protected boolean onDoubleClick(MouseEvent e) { |
| drillDown(); |
| return true; |
| } |
| }.installOn(myList); |
| |
| myList.getInputMap(WHEN_FOCUSED) |
| .put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, SystemInfo.isMac ? InputEvent.META_MASK : InputEvent.CTRL_MASK), ACTION_GO_UP); |
| myList.getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), ACTION_GO_UP); |
| myList.getActionMap().put(ACTION_GO_UP, new AbstractAction() { |
| @Override |
| public void actionPerformed(final ActionEvent e) { |
| goUp(); |
| } |
| }); |
| |
| myList.getActionMap().put("selectAll", new AbstractAction() { |
| @Override |
| public void actionPerformed(final ActionEvent e) { |
| } |
| }); |
| |
| |
| if (enablePopupMenu) { |
| myList.addMouseListener(new PopupHandler() { |
| @Override |
| public void invokePopup(final Component comp, final int x, final int y) { |
| CommanderPanel.this.invokePopup(comp, x, y); |
| } |
| }); |
| } |
| |
| myList.addFocusListener(new FocusAdapter() { |
| @Override |
| public void focusGained(final FocusEvent e) { |
| setActive(true); |
| } |
| |
| @Override |
| public void focusLost(final FocusEvent e) { |
| setActive(false); |
| } |
| }); |
| } |
| |
| public boolean isEnableSearchHighlighting() { |
| return myEnableSearchHighlighting; |
| } |
| |
| public void addHistoryListener(@NotNull CommanderHistoryListener listener) { |
| myHistoryListeners.add(listener); |
| } |
| |
| private void removeHistoryListener(CommanderHistoryListener listener) { |
| myHistoryListeners.remove(listener); |
| } |
| |
| private void updateHistory(boolean elementExpanded) { |
| for (CommanderHistoryListener listener : myHistoryListeners) { |
| listener.historyChanged(getSelectedElement(), elementExpanded); |
| } |
| } |
| |
| public final JList getList() { |
| return myList; |
| } |
| |
| public final AbstractListBuilder.Model getModel() { |
| return myModel; |
| } |
| |
| public void setMoveFocus(final boolean moveFocus) { |
| myMoveFocus = moveFocus; |
| } |
| |
| public void goUp() { |
| if (myBuilder == null) { |
| return; |
| } |
| updateHistory(true); |
| myBuilder.goUp(); |
| updateHistory(false); |
| } |
| |
| public void drillDown() { |
| if (topElementIsSelected()) { |
| goUp(); |
| return; |
| } |
| |
| if (getSelectedValue() == null) { |
| return; |
| } |
| |
| final AbstractTreeNode element = getSelectedNode(); |
| if (element.getChildren().isEmpty()) { |
| if (!shouldDrillDownOnEmptyElement(element)) { |
| navigateSelectedElement(); |
| return; |
| } |
| } |
| |
| if (myBuilder == null) { |
| return; |
| } |
| updateHistory(false); |
| myBuilder.drillDown(); |
| updateHistory(true); |
| } |
| |
| public boolean navigateSelectedElement() { |
| final AbstractTreeNode selectedNode = getSelectedNode(); |
| if (selectedNode != null) { |
| if (selectedNode.canNavigateToSource()) { |
| selectedNode.navigate(true); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| protected boolean shouldDrillDownOnEmptyElement(final AbstractTreeNode node) { |
| return node instanceof ProjectViewNode && ((ProjectViewNode)node).shouldDrillDownOnEmptyElement(); |
| } |
| |
| private boolean topElementIsSelected() { |
| int[] selectedIndices = myList.getSelectedIndices(); |
| return selectedIndices.length == 1 && selectedIndices[0] == 0 && myModel.getElementAt(selectedIndices[0]) instanceof TopLevelNode; |
| } |
| |
| public final void setBuilder(final AbstractListBuilder builder) { |
| myBuilder = builder; |
| removeAll(); |
| |
| myTitlePanel = new JPanel(new BorderLayout()); |
| myTitlePanel.setBackground(UIUtil.getControlColor()); |
| myTitlePanel.setOpaque(true); |
| |
| myParentTitle = new MyTitleLabel(myTitlePanel); |
| myParentTitle.setText(" "); |
| myParentTitle.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)); |
| myParentTitle.setForeground(JBColor.foreground()); |
| myParentTitle.setUI(new RightAlignedLabelUI()); |
| final JPanel panel1 = new JPanel(new BorderLayout()); |
| panel1.setOpaque(false); |
| panel1.add(Box.createHorizontalStrut(10), BorderLayout.WEST); |
| panel1.add(myParentTitle, BorderLayout.CENTER); |
| myTitlePanel.add(panel1, BorderLayout.CENTER); |
| |
| add(myTitlePanel, BorderLayout.NORTH); |
| final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myList); |
| scrollPane.setBorder(null); |
| scrollPane.getVerticalScrollBar().setFocusable(false); // otherwise the scrollbar steals focus and panel switching with tab is broken |
| scrollPane.getHorizontalScrollBar().setFocusable(false); |
| add(scrollPane, BorderLayout.CENTER); |
| |
| myBuilder.setParentTitle(myParentTitle); |
| |
| // TODO[vova,anton] it seems that the code below performs double focus request. Is it OK? |
| myTitlePanel.addMouseListener(new MouseAdapter() { |
| @Override |
| public void mouseClicked(final MouseEvent e) { |
| myList.requestFocus(); |
| } |
| |
| @Override |
| public void mousePressed(final MouseEvent e) { |
| myList.requestFocus(); |
| } |
| }); |
| } |
| |
| public final AbstractListBuilder getBuilder() { |
| return myBuilder; |
| } |
| |
| public final PsiElement getSelectedElement() { |
| Object value = getValueAtIndex(getSelectedNode()); |
| return (PsiElement)(value instanceof PsiElement ? value : null); |
| } |
| |
| public final PsiElement getSelectedElement(int index) { |
| Object elementAtIndex = myModel.getElementAt(index); |
| Object value = getValueAtIndex(elementAtIndex instanceof AbstractTreeNode ? (AbstractTreeNode)elementAtIndex : null); |
| return (PsiElement)(value instanceof PsiElement ? value : null); |
| } |
| |
| public AbstractTreeNode getSelectedNode() { |
| if (myBuilder == null) return null; |
| final int[] indices = myList.getSelectedIndices(); |
| if (indices.length != 1) return null; |
| int index = indices[0]; |
| if (index >= myModel.getSize()) return null; |
| Object elementAtIndex = myModel.getElementAt(index); |
| return elementAtIndex instanceof AbstractTreeNode ? (AbstractTreeNode)elementAtIndex : null; |
| } |
| |
| @NotNull |
| private List<AbstractTreeNode> getSelectedNodes() { |
| if (myBuilder == null) return Collections.emptyList(); |
| final int[] indices = myList.getSelectedIndices(); |
| ArrayList<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>(); |
| for (int index : indices) { |
| if (index >= myModel.getSize()) continue; |
| Object elementAtIndex = myModel.getElementAt(index); |
| AbstractTreeNode node = elementAtIndex instanceof AbstractTreeNode ? (AbstractTreeNode)elementAtIndex : null; |
| if (node != null) { |
| result.add(node); |
| } |
| } |
| return result; |
| } |
| |
| |
| public Object getSelectedValue() { |
| return getValueAtIndex(getSelectedNode()); |
| } |
| |
| private PsiElement[] getSelectedElements() { |
| if (myBuilder == null) return PsiElement.EMPTY_ARRAY; |
| final int[] indices = myList.getSelectedIndices(); |
| |
| final ArrayList<PsiElement> elements = new ArrayList<PsiElement>(); |
| for (int index : indices) { |
| final PsiElement element = getSelectedElement(index); |
| if (element != null) { |
| elements.add(element); |
| } |
| } |
| |
| return PsiUtilCore.toPsiElementArray(elements); |
| } |
| |
| private static Object getValueAtIndex(AbstractTreeNode node) { |
| if (node == null) return null; |
| Object value = node.getValue(); |
| if (value instanceof StructureViewTreeElement) { |
| return ((StructureViewTreeElement)value).getValue(); |
| } |
| return value; |
| } |
| |
| public final void setActive(final boolean active) { |
| myActive = active; |
| if (active) { |
| myTitlePanel.setBackground(DARK_BLUE); |
| myTitlePanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, DARK_BLUE_BRIGHTER, DARK_BLUE_DARKER)); |
| myParentTitle.setForeground(Color.white); |
| } |
| else { |
| final Color color = UIUtil.getPanelBackground(); |
| LOG.assertTrue(color != null); |
| myTitlePanel.setBackground(color); |
| myTitlePanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, color.brighter(), color.darker())); |
| myParentTitle.setForeground(JBColor.foreground()); |
| } |
| final int[] selectedIndices = myList.getSelectedIndices(); |
| if (selectedIndices.length == 0 && myList.getModel().getSize() > 0) { |
| myList.setSelectedIndex(0); |
| if (!myList.hasFocus()) { |
| myList.requestFocus(); |
| } |
| } |
| else if (myList.getModel().getSize() > 0) { |
| // need this to generate SelectionChanged events so that listeners, added by Commander, will be notified |
| myList.setSelectedIndices(selectedIndices); |
| } |
| } |
| |
| public boolean isActive() { |
| return myActive; |
| } |
| |
| private void invokePopup(final Component c, final int x, final int y) { |
| if (myBuilder == null) return; |
| |
| if (myList.getSelectedIndices().length <= 1) { |
| final int popupIndex = myList.locationToIndex(new Point(x, y)); |
| if (popupIndex >= 0) { |
| myList.setSelectedIndex(popupIndex); |
| myList.requestFocus(); |
| } |
| } |
| |
| final ActionGroup group = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_COMMANDER_POPUP); |
| final ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.COMMANDER_POPUP, group); |
| popupMenu.getComponent().show(c, x, y); |
| } |
| |
| public final void dispose() { |
| if (myBuilder != null) { |
| myBuilder.dispose(); |
| myBuilder = null; |
| } |
| myProject = null; |
| } |
| |
| public final void setTitlePanelVisible(final boolean flag) { |
| myTitlePanel.setVisible(flag); |
| } |
| |
| public final Object getDataImpl(final String dataId) { |
| if (myBuilder == null) return null; |
| final Object selectedValue = getSelectedValue(); |
| if (CommonDataKeys.PSI_ELEMENT.is(dataId)) { |
| final PsiElement selectedElement = getSelectedElement(); |
| return selectedElement != null && selectedElement.isValid() ? selectedElement : null; |
| } |
| if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) { |
| return filterInvalidElements(getSelectedElements()); |
| } |
| if (LangDataKeys.PASTE_TARGET_PSI_ELEMENT.is(dataId)) { |
| final AbstractTreeNode parentNode = myBuilder.getParentNode(); |
| final Object element = parentNode != null ? parentNode.getValue() : null; |
| return element instanceof PsiElement && ((PsiElement)element).isValid() ? element : null; |
| } |
| if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) { |
| return getNavigatables(); |
| } |
| if (PlatformDataKeys.COPY_PROVIDER.is(dataId)) { |
| return myCopyPasteDelegator != null ? myCopyPasteDelegator.getCopyProvider() : null; |
| } |
| if (PlatformDataKeys.CUT_PROVIDER.is(dataId)) { |
| return myCopyPasteDelegator != null ? myCopyPasteDelegator.getCutProvider() : null; |
| } |
| if (PlatformDataKeys.PASTE_PROVIDER.is(dataId)) { |
| return myCopyPasteDelegator != null ? myCopyPasteDelegator.getPasteProvider() : null; |
| } |
| if (LangDataKeys.IDE_VIEW.is(dataId)) { |
| return myIdeView; |
| } |
| if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { |
| return myDeleteElementProvider; |
| } |
| if (LangDataKeys.MODULE.is(dataId)) { |
| return selectedValue instanceof Module ? selectedValue : null; |
| } |
| if (ModuleGroup.ARRAY_DATA_KEY.is(dataId)) { |
| return selectedValue instanceof ModuleGroup ? new ModuleGroup[]{(ModuleGroup)selectedValue} : null; |
| } |
| if (LibraryGroupElement.ARRAY_DATA_KEY.is(dataId)) { |
| return selectedValue instanceof LibraryGroupElement ? new LibraryGroupElement[]{(LibraryGroupElement)selectedValue} : null; |
| } |
| if (NamedLibraryElement.ARRAY_DATA_KEY.is(dataId)) { |
| return selectedValue instanceof NamedLibraryElement ? new NamedLibraryElement[]{(NamedLibraryElement)selectedValue} : null; |
| } |
| |
| if (myProjectTreeStructure != null) { |
| return myProjectTreeStructure.getDataFromProviders(getSelectedNodes(), dataId); |
| } |
| |
| return null; |
| } |
| |
| private Navigatable[] getNavigatables() { |
| if (myBuilder == null) return null; |
| final int[] indices = myList.getSelectedIndices(); |
| if (indices == null || indices.length == 0) return null; |
| |
| final ArrayList<Navigatable> elements = new ArrayList<Navigatable>(); |
| for (int index : indices) { |
| final Object element = myModel.getElementAt(index); |
| if (element instanceof AbstractTreeNode) { |
| elements.add((Navigatable)element); |
| } |
| } |
| |
| return elements.toArray(new Navigatable[elements.size()]); |
| } |
| |
| @Nullable |
| private static PsiElement[] filterInvalidElements(final PsiElement[] elements) { |
| if (elements == null || elements.length == 0) { |
| return null; |
| } |
| final List<PsiElement> validElements = new ArrayList<PsiElement>(elements.length); |
| for (final PsiElement element : elements) { |
| if (element.isValid()) { |
| validElements.add(element); |
| } |
| } |
| return validElements.size() == elements.length ? elements : PsiUtilCore.toPsiElementArray(validElements); |
| } |
| |
| protected final Navigatable createEditSourceDescriptor() { |
| return EditSourceUtil.getDescriptor(getSelectedElement()); |
| } |
| |
| public void setProjectTreeStructure(final ProjectAbstractTreeStructureBase projectTreeStructure) { |
| myProjectTreeStructure = projectTreeStructure; |
| } |
| |
| private static final class MyTitleLabel extends JLabel { |
| private final JPanel myPanel; |
| |
| public MyTitleLabel(final JPanel panel) { |
| myPanel = panel; |
| } |
| |
| @Override |
| public void setText(String text) { |
| if (text == null || text.isEmpty()) { |
| text = " "; |
| } |
| super.setText(text); |
| if (myPanel != null) { |
| myPanel.setToolTipText(text.trim().isEmpty() ? null : text); |
| } |
| } |
| } |
| |
| private final class MyDeleteElementProvider implements DeleteProvider { |
| @Override |
| public void deleteElement(@NotNull final DataContext dataContext) { |
| LocalHistoryAction a = LocalHistory.getInstance().startAction(IdeBundle.message("progress.deleting")); |
| try { |
| final PsiElement[] elements = getSelectedElements(); |
| DeleteHandler.deletePsiElement(elements, myProject); |
| } |
| finally { |
| a.finish(); |
| } |
| } |
| |
| @Override |
| public boolean canDeleteElement(@NotNull final DataContext dataContext) { |
| final PsiElement[] elements = getSelectedElements(); |
| return DeleteHandler.shouldEnableDeleteAction(elements); |
| } |
| } |
| |
| private final class MyIdeView implements IdeView { |
| @Override |
| public void selectElement(final PsiElement element) { |
| final boolean isDirectory = element instanceof PsiDirectory; |
| if (!isDirectory) { |
| EditorHelper.openInEditor(element); |
| } |
| ApplicationManager.getApplication().invokeLater(new Runnable() { |
| @Override |
| public void run() { |
| myBuilder.selectElement(element, PsiUtilCore.getVirtualFile(element)); |
| if (!isDirectory) { |
| ApplicationManager.getApplication().invokeLater(new Runnable() { |
| @Override |
| public void run() { |
| if (myMoveFocus) { |
| ToolWindowManager.getInstance(myProject).activateEditorComponent(); |
| } |
| } |
| }); |
| } |
| } |
| }, ModalityState.NON_MODAL); |
| } |
| |
| private PsiDirectory getDirectory() { |
| if (myBuilder == null) return null; |
| final Object parentElement = myBuilder.getParentNode(); |
| if (parentElement instanceof AbstractTreeNode) { |
| final AbstractTreeNode parentNode = (AbstractTreeNode)parentElement; |
| if (!(parentNode.getValue() instanceof PsiDirectory)) return null; |
| return (PsiDirectory)parentNode.getValue(); |
| } |
| else { |
| return null; |
| } |
| } |
| |
| @NotNull |
| @Override |
| public PsiDirectory[] getDirectories() { |
| PsiDirectory directory = getDirectory(); |
| return directory == null ? PsiDirectory.EMPTY_ARRAY : new PsiDirectory[]{directory}; |
| } |
| |
| @Override |
| public PsiDirectory getOrChooseDirectory() { |
| return DirectoryChooserUtil.getOrChooseDirectory(this); |
| } |
| } |
| |
| public static final class MyModel extends AbstractListModel implements AbstractListBuilder.Model { |
| final List myElements = new ArrayList(); |
| |
| @Override |
| public void removeAllElements() { |
| int index1 = myElements.size() - 1; |
| myElements.clear(); |
| if (index1 >= 0) { |
| fireIntervalRemoved(this, 0, index1); |
| } |
| } |
| |
| @Override |
| public void addElement(final Object obj) { |
| int index = myElements.size(); |
| myElements.add(obj); |
| fireIntervalAdded(this, index, index); |
| } |
| |
| @Override |
| public void replaceElements(final List newElements) { |
| removeAllElements(); |
| myElements.addAll(newElements); |
| fireIntervalAdded(this, 0, newElements.size()); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return ArrayUtil.toObjectArray(myElements); |
| } |
| |
| @Override |
| public int indexOf(final Object o) { |
| return myElements.indexOf(o); |
| } |
| |
| @Override |
| public int getSize() { |
| return myElements.size(); |
| } |
| |
| @Override |
| public Object getElementAt(final int index) { |
| return myElements.get(index); |
| } |
| } |
| } |