diff options
Diffstat (limited to 'plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java')
-rw-r--r-- | plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java new file mode 100644 index 000000000000..0c7b57ce999c --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java @@ -0,0 +1,351 @@ +/* + * Copyright 2000-2009 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.palette.impl; + +import com.intellij.designer.LightToolWindowContent; +import com.intellij.ide.palette.PaletteGroup; +import com.intellij.ide.palette.PaletteItem; +import com.intellij.ide.palette.PaletteItemProvider; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.PopupHandler; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.components.JBTabbedPane; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.*; + +/** + * @author yole + */ +public class PaletteWindow extends JPanel implements LightToolWindowContent, DataProvider { + private final Project myProject; + private final ArrayList<PaletteGroupHeader> myGroupHeaders = new ArrayList<PaletteGroupHeader>(); + private final PaletteItemProvider[] myProviders; + private final MyPropertyChangeListener myPropertyChangeListener = new MyPropertyChangeListener(); + private final Set<PaletteGroup> myGroups = new HashSet<PaletteGroup>(); + private final JTabbedPane myTabbedPane = new JBTabbedPane(); + private final JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(); + private final MyListSelectionListener myListSelectionListener = new MyListSelectionListener(); + private PaletteGroupHeader myLastFocusedGroup; + + @NonNls private static final String ourHelpID = "guiDesigner.uiTour.palette"; + + private final DragSourceListener myDragSourceListener = new DragSourceAdapter() { + @Override + public void dragDropEnd(DragSourceDropEvent event) { + Component component = event.getDragSourceContext().getComponent(); + if (!event.getDropSuccess() && + component instanceof PaletteComponentList && + getRootPane() == ((JComponent)component).getRootPane()) { + clearActiveItem(); + } + } + }; + + private GuiEditor myDesigner; + + public PaletteWindow(Project project) { + myProject = project; + myProviders = Extensions.getExtensions(PaletteItemProvider.EP_NAME, project); + + setLayout(new GridLayout(1, 1)); + myScrollPane.addMouseListener(new MyScrollPanePopupHandler()); + myScrollPane.setBorder(null); + KeyStroke escStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + new ClearActiveItemAction().registerCustomShortcutSet(new CustomShortcutSet(escStroke), myScrollPane); + + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + DragSource.getDefaultDragSource().addDragSourceListener(myDragSourceListener); + } + } + + public void dispose() { + removePaletteProviderListener(); + + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + DragSource.getDefaultDragSource().removeDragSourceListener(myDragSourceListener); + } + } + + private void addPaletteProviderListener() { + for (PaletteItemProvider provider : myProviders) { + provider.addListener(myPropertyChangeListener); + } + } + + private void removePaletteProviderListener() { + for (PaletteItemProvider provider : myProviders) { + provider.removeListener(myPropertyChangeListener); + } + } + + public void refreshPaletteIfChanged(@Nullable GuiEditor designer) { + removePaletteProviderListener(); + myDesigner = designer; + if (designer != null) { + addPaletteProviderListener(); + } + + VirtualFile file = designer == null ? null : designer.getFile(); + Set<PaletteGroup> currentGroups = new HashSet<PaletteGroup>(collectCurrentGroups(file)); + if (!currentGroups.equals(myGroups)) { + refreshPalette(file); + } + } + + private void refreshPalette(@Nullable VirtualFile selectedFile) { + for (PaletteGroupHeader groupHeader : myGroupHeaders) { + groupHeader.getComponentList().removeListSelectionListener(myListSelectionListener); + } + String[] oldTabNames = collectTabNames(myGroups); + myTabbedPane.removeAll(); + myGroupHeaders.clear(); + myGroups.clear(); + + final ArrayList<PaletteGroup> currentGroups = collectCurrentGroups(selectedFile); + String[] tabNames = collectTabNames(currentGroups); + if (tabNames.length == 1) { + if (oldTabNames.length != 1) { + remove(myTabbedPane); + add(myScrollPane); + } + + PaletteContentWindow contentWindow = new PaletteContentWindow(); + myScrollPane.getViewport().setView(contentWindow); + + for (PaletteGroup group : currentGroups) { + addGroupToControl(group, contentWindow); + } + + final JComponent view = (JComponent)myScrollPane.getViewport().getView(); + if (view != null) { + view.revalidate(); + for (Component component : view.getComponents()) { + ((JComponent)component).revalidate(); + } + } + } + else { + if (oldTabNames.length <= 1) { + remove(myScrollPane); + add(myTabbedPane); + } + for (String tabName : tabNames) { + PaletteContentWindow contentWindow = new PaletteContentWindow(); + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(contentWindow); + scrollPane.addMouseListener(new MyScrollPanePopupHandler()); + myTabbedPane.add(tabName, scrollPane); + for (PaletteGroup group : currentGroups) { + if (group.getTabName().equals(tabName)) { + addGroupToControl(group, contentWindow); + } + } + } + myTabbedPane.revalidate(); + } + } + + private void addGroupToControl(PaletteGroup group, JComponent control) { + PaletteGroupHeader groupHeader = new PaletteGroupHeader(this, group); + myGroupHeaders.add(groupHeader); + myGroups.add(group); + control.add(groupHeader); + PaletteComponentList componentList = new PaletteComponentList(myProject, this, group); + control.add(componentList); + groupHeader.setComponentList(componentList); + componentList.addListSelectionListener(myListSelectionListener); + } + + private static String[] collectTabNames(final Collection<PaletteGroup> groups) { + Set<String> result = new TreeSet<String>(); + for (PaletteGroup group : groups) { + result.add(group.getTabName()); + } + return ArrayUtil.toStringArray(result); + } + + private ArrayList<PaletteGroup> collectCurrentGroups(@Nullable VirtualFile selectedFile) { + ArrayList<PaletteGroup> result = new ArrayList<PaletteGroup>(); + if (selectedFile != null) { + for (PaletteItemProvider provider : myProviders) { + PaletteGroup[] groups = provider.getActiveGroups(selectedFile); + Collections.addAll(result, groups); + } + } + return result; + } + + public void clearActiveItem() { + if (getActiveItem() == null) return; + for (PaletteGroupHeader group : myGroupHeaders) { + group.getComponentList().clearSelection(); + } + ListSelectionEvent event = new ListSelectionEvent(this, -1, -1, false); + notifySelectionChanged(event); + } + + @Nullable + public PaletteItem getActiveItem() { + for (PaletteGroupHeader groupHeader : myGroupHeaders) { + if (groupHeader.isSelected() && groupHeader.getComponentList().getSelectedValue() != null) { + return (PaletteItem)groupHeader.getComponentList().getSelectedValue(); + } + } + return null; + } + + @Nullable + public <T extends PaletteItem> T getActiveItem(Class<T> cls) { + PaletteItem item = getActiveItem(); + if (item != null && item.getClass().isInstance(item)) { + //noinspection unchecked + return (T)item; + } + return null; + } + + @Nullable + public Object getData(String dataId) { + if (PlatformDataKeys.HELP_ID.is(dataId)) { + return ourHelpID; + } + if (CommonDataKeys.PROJECT.is(dataId)) { + return myProject; + } + PaletteItem item = getActiveItem(); + if (item != null) { + Object data = item.getData(myProject, dataId); + if (data != null) return data; + } + for (PaletteGroupHeader groupHeader : myGroupHeaders) { + if ((groupHeader.isSelected() && groupHeader.getComponentList().getSelectedValue() != null) || groupHeader == myLastFocusedGroup) { + return groupHeader.getGroup().getData(myProject, dataId); + } + } + final int tabCount = collectTabNames(myGroups).length; + if (tabCount > 0) { + JScrollPane activeScrollPane; + if (tabCount == 1) { + activeScrollPane = myScrollPane; + } + else { + activeScrollPane = (JScrollPane)myTabbedPane.getSelectedComponent(); + } + PaletteContentWindow activeContentWindow = (PaletteContentWindow)activeScrollPane.getViewport().getView(); + PaletteGroupHeader groupHeader = activeContentWindow.getLastGroupHeader(); + if (groupHeader != null) { + return groupHeader.getGroup().getData(myProject, dataId); + } + } + return null; + } + + public Project getProject() { + return myProject; + } + + void setLastFocusedGroup(final PaletteGroupHeader focusedGroup) { + myLastFocusedGroup = focusedGroup; + for (PaletteGroupHeader group : myGroupHeaders) { + group.getComponentList().clearSelection(); + } + } + + void notifyKeyEvent(final KeyEvent e) { + if (myDesigner != null) { + if (e.getID() == KeyEvent.KEY_PRESSED) { + myDesigner.paletteKeyPressed(e); + } + else if (e.getID() == KeyEvent.KEY_RELEASED) { + myDesigner.paletteKeyReleased(e); + } + } + } + + void notifyDropActionChanged(int gestureModifiers) { + if (myDesigner != null) { + myDesigner.paletteDropActionChanged(gestureModifiers); + } + } + + void notifySelectionChanged(final ListSelectionEvent event) { + if (myDesigner != null) { + myDesigner.paletteValueChanged(event); + } + } + + private class MyListSelectionListener implements ListSelectionListener { + public void valueChanged(ListSelectionEvent e) { + PaletteComponentList sourceList = (PaletteComponentList)e.getSource(); + for (int i = e.getFirstIndex(); i <= e.getLastIndex(); i++) { + if (sourceList.isSelectedIndex(i)) { + // selection is being added + for (PaletteGroupHeader group : myGroupHeaders) { + if (group.getComponentList() != sourceList) { + group.getComponentList().clearSelection(); + } + } + break; + } + } + notifySelectionChanged(e); + } + } + + private class MyPropertyChangeListener implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent evt) { + refreshPalette(myDesigner.getFile()); + } + } + + private static class MyScrollPanePopupHandler extends PopupHandler { + public void invokePopup(Component comp, int x, int y) { + JScrollPane scrollPane = (JScrollPane)comp; + PaletteContentWindow contentWindow = (PaletteContentWindow)scrollPane.getViewport().getView(); + if (contentWindow != null) { + PaletteGroupHeader groupHeader = contentWindow.getLastGroupHeader(); + if (groupHeader != null) { + groupHeader.showGroupPopupMenu(comp, x, y); + } + } + } + } + + private class ClearActiveItemAction extends AnAction { + public void actionPerformed(AnActionEvent e) { + clearActiveItem(); + } + } +} |