| /* |
| * 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.designer.designSurface; |
| |
| import com.intellij.designer.actions.CommonEditActionsProvider; |
| import com.intellij.designer.designSurface.tools.InputTool; |
| import com.intellij.designer.model.FindComponentVisitor; |
| import com.intellij.designer.model.RadComponent; |
| import com.intellij.designer.model.RadVisualComponent; |
| import com.intellij.ide.DeleteProvider; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.ui.IdeBorderFactory; |
| import com.intellij.ui.SideBorder; |
| import com.intellij.ui.components.JBLayeredPane; |
| import com.intellij.util.containers.IntArrayList; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import java.awt.*; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * @author Alexander Lobas |
| */ |
| public class CaptionPanel extends JBLayeredPane implements DataProvider, DeleteProvider { |
| private static final int SIZE = 16; |
| |
| private final boolean myHorizontal; |
| private final EditableArea myMainArea; |
| private final EditableArea myArea; |
| private final DecorationLayer myDecorationLayer; |
| private final FeedbackLayer myFeedbackLayer; |
| private DefaultActionGroup myActionGroup; |
| private final CommonEditActionsProvider myActionsProvider; |
| private final RadVisualComponent myRootComponent; |
| private List<RadComponent> myRootChildren = Collections.emptyList(); |
| private ICaption myCaption; |
| |
| public CaptionPanel(DesignerEditorPanel designer, boolean horizontal, boolean addBorder) { |
| if (addBorder) { |
| setBorder(IdeBorderFactory.createBorder(horizontal ? SideBorder.BOTTOM : SideBorder.RIGHT)); |
| } |
| |
| setFocusable(true); |
| |
| myHorizontal = horizontal; |
| myMainArea = designer.getSurfaceArea(); |
| |
| myRootComponent = new RadVisualComponent() { |
| @Override |
| public List<RadComponent> getChildren() { |
| return myRootChildren; |
| } |
| |
| @Override |
| public boolean canDelete() { |
| return false; |
| } |
| }; |
| myRootComponent.setNativeComponent(this); |
| if (horizontal) { |
| myRootComponent.setBounds(0, 0, 100000, SIZE); |
| } |
| else { |
| myRootComponent.setBounds(0, 0, SIZE, 100000); |
| } |
| |
| myArea = new ComponentEditableArea(this) { |
| @Override |
| protected void fireSelectionChanged() { |
| super.fireSelectionChanged(); |
| revalidate(); |
| repaint(); |
| } |
| |
| @Override |
| public RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter) { |
| FindComponentVisitor visitor = new FindComponentVisitor(CaptionPanel.this, filter, x, y); |
| myRootComponent.accept(visitor, false); |
| return visitor.getResult(); |
| } |
| |
| @Override |
| public InputTool findTargetTool(int x, int y) { |
| return myDecorationLayer.findTargetTool(x, y); |
| } |
| |
| @Override |
| public void showSelection(boolean value) { |
| myDecorationLayer.showSelection(value); |
| } |
| |
| @Override |
| public ComponentDecorator getRootSelectionDecorator() { |
| return EmptyComponentDecorator.INSTANCE; |
| } |
| |
| @Override |
| public EditOperation processRootOperation(OperationContext context) { |
| return null; |
| } |
| |
| @Override |
| public FeedbackLayer getFeedbackLayer() { |
| return myFeedbackLayer; |
| } |
| |
| @Override |
| public RadComponent getRootComponent() { |
| return myRootComponent; |
| } |
| |
| @Override |
| public ActionGroup getPopupActions() { |
| if (myActionGroup == null) { |
| myActionGroup = new DefaultActionGroup(); |
| myActionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_DELETE)); |
| } |
| return myActionGroup; |
| } |
| |
| @Override |
| public String getPopupPlace() { |
| return "UIDesigner.CaptionPanel"; |
| } |
| }; |
| |
| add(new GlassLayer(designer.getToolProvider(), myArea), DesignerEditorPanel.LAYER_GLASS); |
| |
| myDecorationLayer = new DecorationLayer(designer, myArea); |
| add(myDecorationLayer, DesignerEditorPanel.LAYER_DECORATION); |
| |
| myFeedbackLayer = new FeedbackLayer(designer); |
| add(myFeedbackLayer, DesignerEditorPanel.LAYER_FEEDBACK); |
| |
| myActionsProvider = new CommonEditActionsProvider(designer) { |
| @Override |
| protected EditableArea getArea(DataContext dataContext) { |
| return myArea; |
| } |
| }; |
| |
| myMainArea.addSelectionListener(new ComponentSelectionListener() { |
| @Override |
| public void selectionChanged(EditableArea area) { |
| update(); |
| } |
| }); |
| } |
| |
| public void attachToScrollPane(JScrollPane scrollPane) { |
| scrollPane.getViewport().addChangeListener(new ChangeListener() { |
| public void stateChanged(ChangeEvent e) { |
| repaint(); |
| } |
| }); |
| } |
| |
| public void doLayout() { |
| for (int i = getComponentCount() - 1; i >= 0; i--) { |
| Component component = getComponent(i); |
| component.setBounds(0, 0, getWidth(), getHeight()); |
| } |
| } |
| |
| @Override |
| public Dimension getPreferredSize() { |
| return new Dimension(SIZE, SIZE); |
| } |
| |
| @Override |
| public Dimension getMinimumSize() { |
| return getPreferredSize(); |
| } |
| |
| @Override |
| public Object getData(@NonNls String dataId) { |
| if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { |
| return this; |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean canDeleteElement(@NotNull DataContext dataContext) { |
| return myActionsProvider.canDeleteElement(dataContext); |
| } |
| |
| @Override |
| public void deleteElement(@NotNull DataContext dataContext) { |
| myActionsProvider.deleteElement(dataContext); |
| } |
| |
| public void update() { |
| List<RadComponent> selection = myMainArea.getSelection(); |
| if (selection.size() != 1) { |
| if (myCaption != null) { |
| myCaption = null; |
| myRootComponent.setLayout(null); |
| myRootChildren = Collections.emptyList(); |
| myArea.deselectAll(); |
| revalidate(); |
| repaint(); |
| } |
| return; |
| } |
| |
| boolean update = !myRootChildren.isEmpty(); |
| |
| IntArrayList oldSelection = null; |
| if (myCaption != null) { |
| oldSelection = new IntArrayList(); |
| for (RadComponent component : myArea.getSelection()) { |
| oldSelection.add(myRootChildren.indexOf(component)); |
| } |
| } |
| |
| myArea.deselectAll(); |
| myRootComponent.setLayout(null); |
| |
| ICaption caption = null; |
| RadComponent component = selection.get(0); |
| RadComponent parent = component.getParent(); |
| |
| if (parent != null) { |
| caption = parent.getLayout().getCaption(component); |
| } |
| if (caption == null) { |
| caption = component.getCaption(); |
| } |
| |
| if (caption == null) { |
| myRootChildren = Collections.emptyList(); |
| } |
| else { |
| myRootComponent.setLayout(caption.getCaptionLayout(myMainArea, myHorizontal)); |
| |
| myRootChildren = caption.getCaptionChildren(myMainArea, myHorizontal); |
| for (RadComponent child : myRootChildren) { |
| child.setParent(myRootComponent); |
| } |
| |
| if (myCaption == caption) { |
| List<RadComponent> newSelection = new ArrayList<RadComponent>(); |
| int componentSize = myRootChildren.size(); |
| int selectionSize = oldSelection.size(); |
| |
| for (int i = 0; i < selectionSize; i++) { |
| int index = oldSelection.get(i); |
| if (0 <= index && index < componentSize) { |
| newSelection.add(myRootChildren.get(index)); |
| } |
| } |
| |
| if (!newSelection.isEmpty()) { |
| myArea.setSelection(newSelection); |
| } |
| } |
| |
| update |= !myRootChildren.isEmpty(); |
| } |
| |
| myCaption = caption; |
| |
| if (update) { |
| revalidate(); |
| repaint(); |
| } |
| } |
| } |