summaryrefslogtreecommitdiff
path: root/plugins/ui-designer/src/com/intellij/ide
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ui-designer/src/com/intellij/ide')
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/PaletteDragEventListener.java24
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/PaletteGroup.java65
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/PaletteItem.java56
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/PaletteItemProvider.java34
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java403
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteContentWindow.java114
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteGroupHeader.java211
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java118
-rw-r--r--plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java351
9 files changed, 1376 insertions, 0 deletions
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/PaletteDragEventListener.java b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteDragEventListener.java
new file mode 100644
index 000000000000..1a6b681b2a48
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteDragEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+/**
+ * @author yole
+ */
+public interface PaletteDragEventListener {
+ void dropActionChanged(int gestureModifiers);
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/PaletteGroup.java b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteGroup.java
new file mode 100644
index 000000000000..a19c1ab8e60d
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteGroup.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public interface PaletteGroup {
+ PaletteGroup[] EMPTY_ARRAY = new PaletteGroup[0];
+
+ PaletteItem[] getItems();
+
+ /**
+ * Returns the text of the group header for the palette group.
+ *
+ * @return the text of the group header for the palette group, or null if no header should be shown.
+ */
+ @Nullable String getName();
+
+ String getTabName();
+
+ /**
+ * Returns the action group from which the context menu is built when the palette
+ * item is right-clicked.
+ *
+ * @return the action group, or null if no context menu should be shown.
+ */
+ @Nullable ActionGroup getPopupActionGroup();
+
+ /**
+ * Returns the data for the specified data constant.
+ *
+ * @param project the project in the context of which data is requested.
+ * @param dataId the data constant id (see {@link com.intellij.openapi.actionSystem.PlatformDataKeys}).
+ * @return the data item, or null if no data is available for this constant.
+ */
+ @Nullable Object getData(Project project, String dataId);
+
+ /**
+ * Processes the drop of a palette item on the specified index in the palette group.
+ *
+ * @param project the project to which the drop target palette belongs.
+ * @param item the dropped item.
+ * @param index the index at which the dropped item should be inserted (from 0 to getItems().length).
+ */
+ void handleDrop(Project project, PaletteItem item, int index);
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItem.java b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItem.java
new file mode 100644
index 000000000000..372839d67266
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItem.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import com.intellij.ide.dnd.DnDDragStartBean;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.ColoredListCellRenderer;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author yole
+ */
+public interface PaletteItem {
+ void customizeCellRenderer(ColoredListCellRenderer cellRenderer,
+ boolean selected,
+ boolean hasFocus);
+
+ /**
+ * Processes dragging the item.
+ *
+ * @return the drag start bean for the drag process, or null if the item cannot be dragged.
+ */
+ @Nullable DnDDragStartBean startDragging();
+
+ /**
+ * Returns the action group from which the context menu is built when the palette
+ * item is right-clicked.
+ *
+ * @return the action group, or null if no context menu should be shown.
+ */
+ @Nullable ActionGroup getPopupActionGroup();
+
+ /**
+ * Returns the data for the specified data constant.
+ *
+ * @param project the project in the context of which data is requested.
+ * @param dataId the data constant id (see {@link com.intellij.openapi.actionSystem.PlatformDataKeys}).
+ * @return the data item, or null if no data is available for this constant.
+ */
+ @Nullable Object getData(Project project, String dataId);
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItemProvider.java b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItemProvider.java
new file mode 100644
index 000000000000..3f1b99d36f52
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/PaletteItemProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.vfs.VirtualFile;
+
+import java.beans.PropertyChangeListener;
+
+/**
+ * @author yole
+ */
+public interface PaletteItemProvider {
+ ExtensionPointName<PaletteItemProvider> EP_NAME = ExtensionPointName.create("com.intellij.paletteItemProvider");
+
+ PaletteGroup[] getActiveGroups(VirtualFile virtualFile);
+
+ void addListener(PropertyChangeListener listener);
+ void removeListener(PropertyChangeListener listener);
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java
new file mode 100644
index 000000000000..77b58a922a87
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2000-2012 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.ide.dnd.*;
+import com.intellij.ide.palette.PaletteGroup;
+import com.intellij.ide.palette.PaletteItem;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.ActionPopupMenu;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.PopupHandler;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.PlatformColors;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.plaf.basic.BasicListUI;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * @author yole
+ */
+public class PaletteComponentList extends JBList {
+ private final Project myProject;
+ private final PaletteWindow myPalette;
+ private final PaletteGroup myGroup;
+ private int myHoverIndex = -1;
+ private int myBeforeClickSelectedRow = -1;
+ private int myDropTargetIndex = -1;
+ private boolean myNeedClearSelection = false;
+
+ public PaletteComponentList(Project project, PaletteWindow palette, PaletteGroup group) {
+ myProject = project;
+ myPalette = palette;
+ myGroup = group;
+ setModel(new AbstractListModel() {
+ public int getSize() {
+ return myGroup.getItems().length;
+ }
+
+ public Object getElementAt(int index) {
+ return myGroup.getItems() [index];
+ }
+ });
+
+ addMouseListener(new MouseAdapter() {
+ @Override public void mouseEntered(MouseEvent e) {
+ setHoverIndex(locationToIndex(e.getPoint()));
+ }
+
+ @Override public void mouseExited(MouseEvent e) {
+ setHoverIndex(-1);
+ }
+
+ @Override public void mousePressed(MouseEvent e) {
+ myNeedClearSelection = (SwingUtilities.isLeftMouseButton(e) &&
+ myBeforeClickSelectedRow >= 0 &&
+ locationToIndex(e.getPoint()) == myBeforeClickSelectedRow &&
+ !UIUtil.isControlKeyDown(e) && !e.isShiftDown());
+ }
+
+ @Override public void mouseReleased(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) &&
+ myBeforeClickSelectedRow >= 0 &&
+ locationToIndex(e.getPoint()) == myBeforeClickSelectedRow &&
+ !UIUtil.isControlKeyDown(e) && !e.isShiftDown() && myNeedClearSelection) {
+ clearSelection();
+ }
+ }
+ });
+
+ addMouseListener(new PopupHandler() {
+ public void invokePopup(final Component comp, final int x, final int y) {
+ requestFocusInWindow();
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ int index = locationToIndex(new Point(x, y));
+ PaletteItem[] items = myGroup.getItems();
+ if (index >= 0 && index < items.length) {
+ if (getSelectedIndex() != index) {
+ addSelectionInterval(index, index);
+ }
+ PaletteItem item = items [index];
+ ActionGroup group = item.getPopupActionGroup();
+ if (group != null) {
+ ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group);
+ popupMenu.getComponent().show(comp, x, y);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ addMouseMotionListener(new MouseMotionAdapter() {
+ public void mouseMoved(MouseEvent e) {
+ setHoverIndex(locationToIndex(e.getPoint()));
+ }
+ });
+
+ addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e) {
+ myPalette.notifyKeyEvent(e);
+ }
+
+ public void keyReleased(KeyEvent e) {
+ myPalette.notifyKeyEvent(e);
+ }
+
+ public void keyTyped(KeyEvent e) {
+ myPalette.notifyKeyEvent(e);
+ }
+ });
+
+ setCellRenderer(new ComponentCellRenderer());
+
+ setVisibleRowCount(0);
+ setLayoutOrientation(HORIZONTAL_WRAP);
+ setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ final DnDManager dndManager = DnDManager.getInstance();
+ dndManager.registerSource(new MyDnDSource(), this);
+ dndManager.registerTarget(new MyDnDTarget(), this);
+
+ initActions();
+ }
+
+ private void setHoverIndex(final int index) {
+ if (index != myHoverIndex) {
+ if (myHoverIndex >= 0) repaint(getCellBounds(myHoverIndex, myHoverIndex));
+ myHoverIndex = index;
+ if (myHoverIndex >= 0) repaint(getCellBounds(myHoverIndex, myHoverIndex));
+ }
+ }
+
+ private void setDropTargetIndex(final int index) {
+ if (index != myDropTargetIndex) {
+ myDropTargetIndex = index;
+ repaint();
+ }
+ }
+
+ @Override public void updateUI() {
+ setUI(new ComponentListUI());
+ invalidate();
+ }
+
+ private void initActions() {
+ @NonNls ActionMap map = getActionMap();
+ map.put( "selectPreviousRow", new MoveFocusAction( map.get( "selectPreviousRow" ), false ) );
+ map.put( "selectNextRow", new MoveFocusAction( map.get( "selectNextRow" ), true ) );
+ map.put( "selectPreviousColumn", new MoveFocusAction( new ChangeColumnAction( map.get( "selectPreviousColumn" ), false ), false ) );
+ map.put( "selectNextColumn", new MoveFocusAction( new ChangeColumnAction( map.get( "selectNextColumn" ), true ), true ) );
+ }
+
+ Integer myTempWidth;
+
+ public int getWidth () {
+ return (myTempWidth == null) ? super.getWidth () : myTempWidth.intValue ();
+ }
+
+ public int getPreferredHeight(final int width) {
+ myTempWidth = width;
+ try {
+ return getUI().getPreferredSize(this).height;
+ }
+ finally {
+ myTempWidth = null;
+ }
+ }
+
+ public void takeFocusFrom(PaletteGroupHeader paletteGroup, int indexToSelect) {
+ if (indexToSelect == -1) {
+ //this is not 'our' CategoryButton so we'll assume it's the one below this category list
+ indexToSelect = getModel().getSize() - 1;
+ }
+ else if (getModel().getSize() == 0) {
+ indexToSelect = -1;
+ }
+ requestFocus();
+ setSelectedIndex(indexToSelect);
+ if (indexToSelect >= 0) {
+ ensureIndexIsVisible(indexToSelect);
+ }
+ }
+
+ @Override protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ if (myDropTargetIndex >= 0) {
+ int dropLineY;
+ Rectangle rc;
+ if (myDropTargetIndex == myGroup.getItems().length) {
+ rc = getCellBounds(myDropTargetIndex-1, myDropTargetIndex-1);
+ dropLineY = (int)rc.getMaxY()-1;
+ }
+ else {
+ rc = getCellBounds(myDropTargetIndex, myDropTargetIndex);
+ dropLineY = rc.y;
+ }
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setColor(PlatformColors.BLUE);
+ g2d.setStroke(new BasicStroke(2.0f));
+ g2d.drawLine(rc.x, dropLineY, rc.x+rc.width, dropLineY);
+ g2d.drawLine(rc.x, dropLineY-2, rc.x, dropLineY+2);
+ g2d.drawLine(rc.x+rc.width, dropLineY-2, rc.x+rc.width, dropLineY+2);
+ }
+ }
+
+ class ComponentListUI extends BasicListUI {
+ private ComponentListListener myListener;
+
+ @Override protected void updateLayoutState() {
+ super.updateLayoutState();
+
+ if (list.getLayoutOrientation() == JList.HORIZONTAL_WRAP) {
+ Insets insets = list.getInsets();
+ int listWidth = list.getWidth() - (insets.left + insets.right);
+ if (listWidth >= cellWidth) {
+ int columnCount = listWidth / cellWidth;
+ cellWidth = (columnCount == 0) ? 1 : listWidth / columnCount;
+ }
+ }
+ }
+
+ @Override protected void installListeners() {
+ myListener = new ComponentListListener();
+ addMouseListener(myListener);
+ super.installListeners();
+ }
+
+ @Override
+ protected void uninstallListeners() {
+ if (myListener != null) {
+ removeMouseListener(myListener);
+ }
+ super.uninstallListeners();
+ }
+
+ private class ComponentListListener extends MouseAdapter {
+ @Override public void mousePressed(MouseEvent e) {
+ myBeforeClickSelectedRow = list.getSelectedIndex();
+ }
+ }
+ }
+
+ private static class ComponentCellRenderer extends ColoredListCellRenderer {
+ protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ PaletteItem paletteItem = (PaletteItem) value;
+ clear();
+ paletteItem.customizeCellRenderer(this, selected, hasFocus);
+ }
+ }
+
+ private class MoveFocusAction extends AbstractAction {
+ private final Action defaultAction;
+ private final boolean focusNext;
+
+ public MoveFocusAction(Action defaultAction, boolean focusNext) {
+ this.defaultAction = defaultAction;
+ this.focusNext = focusNext;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int selIndexBefore = getSelectedIndex();
+ defaultAction.actionPerformed(e);
+ int selIndexCurrent = getSelectedIndex();
+ if (selIndexBefore != selIndexCurrent) return;
+
+ if (focusNext && 0 == selIndexCurrent) return;
+
+ KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Container container = kfm.getCurrentFocusCycleRoot();
+ FocusTraversalPolicy policy = container.getFocusTraversalPolicy();
+ if (null == policy) policy = kfm.getDefaultFocusTraversalPolicy();
+ Component next = focusNext
+ ? policy.getComponentAfter(container, PaletteComponentList.this)
+ : policy.getComponentBefore(container, PaletteComponentList.this);
+ if (null != next && next instanceof PaletteGroupHeader) {
+ clearSelection();
+ next.requestFocus();
+ ((PaletteGroupHeader)next).scrollRectToVisible(next.getBounds());
+ }
+ }
+ }
+
+ private class ChangeColumnAction extends AbstractAction {
+ private final Action defaultAction;
+ private final boolean selectNext;
+
+ public ChangeColumnAction(Action defaultAction, boolean selectNext) {
+ this.defaultAction = defaultAction;
+ this.selectNext = selectNext;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int selIndexBefore = getSelectedIndex();
+ defaultAction.actionPerformed(e);
+ int selIndexCurrent = getSelectedIndex();
+ if ((selectNext && selIndexBefore < selIndexCurrent) || (!selectNext && selIndexBefore > selIndexCurrent)) return;
+
+ if (selectNext) {
+ if (selIndexCurrent == selIndexBefore + 1) selIndexCurrent++;
+ if (selIndexCurrent < getModel().getSize() - 1) {
+ setSelectedIndex(selIndexCurrent + 1);
+ scrollRectToVisible(getCellBounds(selIndexCurrent + 1, selIndexCurrent + 1));
+ }
+ }
+ else {
+ if (selIndexCurrent > 0) {
+ setSelectedIndex(selIndexCurrent - 1);
+ scrollRectToVisible(getCellBounds(selIndexCurrent - 1, selIndexCurrent - 1));
+ }
+ }
+ }
+ }
+
+ private class MyDnDTarget implements DnDTarget {
+
+ public boolean update(DnDEvent aEvent) {
+ setHoverIndex(-1);
+ if (aEvent.getAttachedObject() instanceof PaletteItem) {
+ setDropTargetIndex(locationToTargetIndex(aEvent.getPoint()));
+ aEvent.setDropPossible(true);
+ }
+ else {
+ setDropTargetIndex(-1);
+ aEvent.setDropPossible(false);
+ }
+ return false;
+ }
+
+ public void drop(DnDEvent aEvent) {
+ setDropTargetIndex(-1);
+ if (aEvent.getAttachedObject() instanceof PaletteItem) {
+ int index = locationToTargetIndex(aEvent.getPoint());
+ if (index >= 0) {
+ myGroup.handleDrop(myProject, (PaletteItem) aEvent.getAttachedObject(), index);
+ }
+ }
+ }
+
+ public void cleanUpOnLeave() {
+ setDropTargetIndex(-1);
+ }
+
+ private int locationToTargetIndex(Point location) {
+ int row = locationToIndex(location);
+ if (row < 0) {
+ return -1;
+ }
+ Rectangle rc = getCellBounds(row, row);
+ return location.y < rc.getCenterY() ? row : row + 1;
+ }
+
+ public void updateDraggedImage(Image image, Point dropPoint, Point imageOffset) {
+ }
+ }
+
+ private class MyDnDSource implements DnDSource {
+ public boolean canStartDragging(DnDAction action, Point dragOrigin) {
+ int index = locationToIndex(dragOrigin);
+ return index >= 0 && myGroup.getItems() [index].startDragging() != null;
+ }
+
+ public DnDDragStartBean startDragging(DnDAction action, Point dragOrigin) {
+ int index = locationToIndex(dragOrigin);
+ if (index < 0) return null;
+ return myGroup.getItems() [index].startDragging();
+ }
+
+ @Nullable
+ public Pair<Image, Point> createDraggedImage(DnDAction action, Point dragOrigin) {
+ return null;
+ }
+
+ public void dragDropEnd() {
+ }
+
+ public void dropActionChanged(final int gestureModifiers) {
+ myPalette.notifyDropActionChanged(gestureModifiers);
+ }
+ }
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteContentWindow.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteContentWindow.java
new file mode 100644
index 000000000000..b5aaccad7b29
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteContentWindow.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author yole
+ */
+public class PaletteContentWindow extends JPanel implements Scrollable {
+ public PaletteContentWindow() {
+ setLayout(new PaletteLayoutManager());
+ }
+
+ public Dimension getPreferredScrollableViewportSize() {
+ return getPreferredSize();
+ }
+
+ public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+ return 20;
+ }
+
+ public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+ return 100;
+ }
+
+ public boolean getScrollableTracksViewportWidth() {
+ return true;
+ }
+
+ public boolean getScrollableTracksViewportHeight() {
+ return false;
+ }
+
+ @Nullable PaletteGroupHeader getLastGroupHeader() {
+ PaletteGroupHeader result = null;
+ for(Component comp: getComponents()) {
+ if (comp instanceof PaletteGroupHeader) {
+ result = (PaletteGroupHeader) comp;
+ }
+ }
+ return result;
+ }
+
+ private static class PaletteLayoutManager implements LayoutManager {
+
+ public void addLayoutComponent(String name, Component comp) {
+ }
+
+ public void layoutContainer(Container parent) {
+ int width = parent.getWidth();
+
+ int height = 0;
+ for(Component c: parent.getComponents()) {
+ if (c instanceof PaletteGroupHeader) {
+ PaletteGroupHeader groupHeader = (PaletteGroupHeader) c;
+ groupHeader.setLocation(0, height);
+ if (groupHeader.isVisible()) {
+ groupHeader.setSize(width, groupHeader.getPreferredSize().height);
+ height += groupHeader.getPreferredSize().height;
+ }
+ else {
+ groupHeader.setSize(0, 0);
+ }
+ if (groupHeader.isSelected() || !groupHeader.isVisible()) {
+ PaletteComponentList componentList = groupHeader.getComponentList();
+ componentList.setSize(width, componentList.getPreferredSize().height);
+ componentList.setLocation(0, height);
+ height += componentList.getHeight();
+ }
+ }
+ }
+ }
+
+ public Dimension minimumLayoutSize(Container parent) {
+ return new Dimension(0, 0);
+ }
+
+ public Dimension preferredLayoutSize(Container parent) {
+ int height = 0;
+ int width = parent.getWidth();
+ for(Component c: parent.getComponents()) {
+ if (c instanceof PaletteGroupHeader) {
+ PaletteGroupHeader groupHeader = (PaletteGroupHeader) c;
+ height += groupHeader.getHeight();
+ if (groupHeader.isSelected()) {
+ height += groupHeader.getComponentList().getPreferredHeight(width);
+ }
+ }
+ }
+ return new Dimension(10 /* not used - tracks viewports width*/, height);
+ }
+
+ public void removeLayoutComponent(Component comp) {
+ }
+ }
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteGroupHeader.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteGroupHeader.java
new file mode 100644
index 000000000000..c98caefa3f75
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteGroupHeader.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2000-2013 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.ide.dnd.DnDEvent;
+import com.intellij.ide.dnd.DnDManager;
+import com.intellij.ide.dnd.DnDTarget;
+import com.intellij.ide.palette.PaletteGroup;
+import com.intellij.ide.palette.PaletteItem;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.PopupHandler;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.CompoundBorder;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * @author yole
+ */
+public class PaletteGroupHeader extends JCheckBox implements DataProvider {
+ private final PaletteWindow myPaletteWindow;
+ private PaletteComponentList myComponentList;
+ private final PaletteGroup myGroup;
+
+ public PaletteGroupHeader(PaletteWindow paletteWindow, PaletteGroup group) {
+ myPaletteWindow = paletteWindow;
+ myGroup = group;
+ if (group.getName() == null) {
+ setVisible(false);
+ }
+ else {
+ setText(group.getName());
+ }
+ setSelected(true);
+ addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (myComponentList != null) {
+ myComponentList.setVisible(isSelected());
+ }
+ }
+ });
+
+ addMouseListener(new PopupHandler() {
+ public void invokePopup(Component comp, int x, int y) {
+ myPaletteWindow.setLastFocusedGroup(PaletteGroupHeader.this);
+ showGroupPopupMenu(comp, x, y);
+ }
+ });
+
+ setIcon(UIUtil.getTreeCollapsedIcon());
+ setSelectedIcon(UIUtil.getTreeExpandedIcon());
+ setFont(getFont().deriveFont(Font.BOLD));
+ setFocusPainted(false);
+ setMargin(new Insets(0, 3, 0, 3));
+ setOpaque(true);
+ if (getBorder() instanceof CompoundBorder) { // from BasicLookAndFeel
+ Dimension pref = getPreferredSize();
+ pref.height -= 3;
+ setPreferredSize(pref);
+ }
+
+ DnDManager.getInstance().registerTarget(new DnDTarget() {
+ public boolean update(DnDEvent aEvent) {
+ setBorderPainted(true);
+ aEvent.setDropPossible(aEvent.getAttachedObject() instanceof PaletteItem);
+ return true;
+ }
+
+ public void drop(DnDEvent aEvent) {
+ setBorderPainted(false);
+ if (aEvent.getAttachedObject() instanceof PaletteItem) {
+ myGroup.handleDrop(myPaletteWindow.getProject(), (PaletteItem) aEvent.getAttachedObject(), -1);
+ }
+ }
+
+ public void cleanUpOnLeave() {
+ setBorderPainted(false);
+ }
+
+ public void updateDraggedImage(Image image, Point dropPoint, Point imageOffset) {
+ }
+ }, this);
+
+ addFocusListener(new FocusAdapter() {
+ @Override public void focusGained(FocusEvent e) {
+ myPaletteWindow.setLastFocusedGroup(PaletteGroupHeader.this);
+ }
+ });
+
+ initActions();
+ }
+
+ public void showGroupPopupMenu(final Component comp, final int x, final int y) {
+ ActionGroup group = myGroup.getPopupActionGroup();
+ if (group != null) {
+ ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group);
+ popupMenu.getComponent().show(comp, x, y);
+ }
+ }
+
+ private void initActions() {
+ @NonNls InputMap inputMap = getInputMap(WHEN_FOCUSED);
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "moveFocusDown");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "moveFocusUp");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "collapse");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "expand");
+
+ @NonNls ActionMap actionMap = getActionMap();
+ actionMap.put("moveFocusDown", new MoveFocusAction(true));
+ actionMap.put("moveFocusUp", new MoveFocusAction(false));
+ actionMap.put("collapse", new ExpandAction(false));
+ actionMap.put("expand", new ExpandAction(true));
+ }
+
+ @Override public Color getBackground() {
+ if (isFocusOwner()) {
+ return UIUtil.getListSelectionBackground();
+ }
+ return super.getBackground();
+ }
+
+ @Override public Color getForeground() {
+ if (isFocusOwner()) {
+ return UIUtil.getListSelectionForeground();
+ }
+ return super.getForeground();
+ }
+
+ public void setComponentList(final PaletteComponentList componentList) {
+ myComponentList = componentList;
+ }
+
+ public PaletteComponentList getComponentList() {
+ return myComponentList;
+ }
+
+ public PaletteGroup getGroup() {
+ return myGroup;
+ }
+
+ @Nullable public Object getData(String dataId) {
+ Object data = myPaletteWindow.getData(dataId);
+ if (data != null) return data;
+ Project project = CommonDataKeys.PROJECT.getData(myPaletteWindow);
+ return myGroup.getData(project, dataId);
+ }
+
+ private class MoveFocusAction extends AbstractAction {
+ private final boolean moveDown;
+
+ public MoveFocusAction(boolean moveDown) {
+ this.moveDown = moveDown;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Container container = kfm.getCurrentFocusCycleRoot();
+ FocusTraversalPolicy policy = container.getFocusTraversalPolicy();
+ if (null == policy) policy = kfm.getDefaultFocusTraversalPolicy();
+ Component next =
+ moveDown ? policy.getComponentAfter(container, PaletteGroupHeader.this) : policy.getComponentBefore(container, PaletteGroupHeader.this);
+ if (null != next && next instanceof PaletteComponentList) {
+ final PaletteComponentList list = (PaletteComponentList)next;
+ if (list.getModel().getSize() != 0) {
+ list.takeFocusFrom(PaletteGroupHeader.this, list == myComponentList ? 0 : -1);
+ return;
+ }
+ else {
+ next = moveDown ? policy.getComponentAfter(container, next) : policy.getComponentBefore(container, next);
+ }
+ }
+ if (null != next && next instanceof PaletteGroupHeader) {
+ next.requestFocus();
+ }
+ }
+ }
+
+ private class ExpandAction extends AbstractAction {
+ private final boolean expand;
+
+ public ExpandAction(boolean expand) {
+ this.expand = expand;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (expand == isSelected()) return;
+ setSelected(expand);
+ if (myComponentList != null) {
+ myComponentList.setVisible(isSelected());
+ }
+ }
+ }
+}
diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java
new file mode 100644
index 000000000000..c6fe8756d1f5
--- /dev/null
+++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java
@@ -0,0 +1,118 @@
+/*
+ * 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.palette.impl;
+
+import com.intellij.designer.DesignerEditorPanelFacade;
+import com.intellij.designer.LightToolWindow;
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentManager;
+import com.intellij.uiDesigner.AbstractToolWindowManager;
+import com.intellij.uiDesigner.designSurface.GuiEditor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Alexander Lobas
+ */
+public class PaletteToolWindowManager extends AbstractToolWindowManager {
+ private final PaletteWindow myToolWindowPanel;
+
+ public PaletteToolWindowManager(Project project, FileEditorManager fileEditorManager) {
+ super(project, fileEditorManager);
+ myToolWindowPanel = ApplicationManager.getApplication().isHeadlessEnvironment() ? null : new PaletteWindow(project);
+ }
+
+ public static PaletteWindow getInstance(GuiEditor designer) {
+ PaletteToolWindowManager manager = getInstance(designer.getProject());
+ if (manager.isEditorMode()) {
+ return (PaletteWindow)manager.getContent(designer);
+ }
+ return manager.myToolWindowPanel;
+ }
+
+ public static PaletteToolWindowManager getInstance(Project project) {
+ return project.getComponent(PaletteToolWindowManager.class);
+ }
+
+ @Override
+ protected void initToolWindow() {
+ myToolWindow = ToolWindowManager.getInstance(myProject)
+ .registerToolWindow(IdeBundle.message("toolwindow.palette"), false, getAnchor(), myProject, true);
+ myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette);
+ initGearActions();
+
+ ContentManager contentManager = myToolWindow.getContentManager();
+ Content content = contentManager.getFactory().createContent(myToolWindowPanel, null, false);
+ content.setCloseable(false);
+ content.setPreferredFocusableComponent(myToolWindowPanel);
+ contentManager.addContent(content);
+ contentManager.setSelectedContent(content, true);
+ myToolWindow.setAvailable(false, null);
+ }
+
+ @Override
+ protected void updateToolWindow(@Nullable DesignerEditorPanelFacade designer) {
+ myToolWindowPanel.refreshPaletteIfChanged((GuiEditor)designer);
+
+ if (designer == null) {
+ myToolWindow.setAvailable(false, null);
+ }
+ else {
+ myToolWindow.setAvailable(true, null);
+ myToolWindow.show(null);
+ }
+ }
+
+ @Override
+ protected ToolWindowAnchor getAnchor() {
+ return ToolWindowAnchor.RIGHT;
+ }
+
+ @Override
+ protected LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer) {
+ PaletteWindow palettePanel = new PaletteWindow(myProject);
+ palettePanel.refreshPaletteIfChanged((GuiEditor)designer);
+
+ return createContent(designer,
+ palettePanel,
+ IdeBundle.message("toolwindow.palette"),
+ AllIcons.Toolwindows.ToolWindowPalette,
+ palettePanel,
+ palettePanel,
+ 180,
+ null);
+ }
+
+ @Override
+ public void disposeComponent() {
+ if (myToolWindowPanel != null) {
+ myToolWindowPanel.dispose();
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getComponentName() {
+ return "PaletteManager";
+ }
+} \ No newline at end of file
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();
+ }
+ }
+}