| /* |
| * 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.uiDesigner.radComponents; |
| |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.uiDesigner.UIDesignerBundle; |
| import com.intellij.uiDesigner.UIFormXmlConstants; |
| import com.intellij.uiDesigner.XmlWriter; |
| import com.intellij.uiDesigner.core.GridConstraints; |
| import com.intellij.uiDesigner.designSurface.ComponentDragObject; |
| import com.intellij.uiDesigner.designSurface.ComponentDropLocation; |
| import com.intellij.uiDesigner.designSurface.FeedbackLayer; |
| import com.intellij.uiDesigner.designSurface.GuiEditor; |
| import com.intellij.uiDesigner.lw.LwContainer; |
| import com.intellij.uiDesigner.propertyInspector.Property; |
| import com.intellij.uiDesigner.propertyInspector.PropertyEditor; |
| import com.intellij.uiDesigner.propertyInspector.PropertyRenderer; |
| import com.intellij.uiDesigner.propertyInspector.editors.AbstractTextFieldEditor; |
| import com.intellij.uiDesigner.propertyInspector.editors.ComponentEditor; |
| import com.intellij.uiDesigner.propertyInspector.properties.HGapProperty; |
| import com.intellij.uiDesigner.propertyInspector.properties.VGapProperty; |
| import com.intellij.uiDesigner.propertyInspector.renderers.ComponentRenderer; |
| import com.intellij.uiDesigner.propertyInspector.renderers.LabelPropertyRenderer; |
| import com.intellij.uiDesigner.snapShooter.SnapshotContext; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.CardLayout; |
| import java.awt.LayoutManager; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.lang.reflect.Field; |
| import java.util.Vector; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| public class RadCardLayoutManager extends RadLayoutManager { |
| @Nullable |
| public String getName() { |
| return UIFormXmlConstants.LAYOUT_CARD; |
| } |
| |
| @Override @Nullable |
| public LayoutManager createLayout() { |
| return new CardLayout(); |
| } |
| |
| @Override |
| public void readLayout(LwContainer lwContainer, RadContainer radContainer) throws Exception { |
| String defaultCard = (String)lwContainer.getClientProperty(UIFormXmlConstants.LAYOUT_CARD); |
| DefaultCardProperty.INSTANCE.setValue(radContainer, defaultCard); |
| } |
| |
| public void writeChildConstraints(final XmlWriter writer, final RadComponent child) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_CARD); |
| try { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_NAME, (String) child.getCustomLayoutConstraints()); |
| } |
| finally { |
| writer.endElement(); |
| } |
| } |
| |
| @Override |
| public void writeLayout(final XmlWriter writer, final RadContainer radContainer) { |
| CardLayout layout = (CardLayout) radContainer.getLayout(); |
| |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_HGAP, layout.getHgap()); |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_VGAP, layout.getVgap()); |
| |
| String defaultCard = DefaultCardProperty.INSTANCE.getValue(radContainer); |
| if (!StringUtil.isEmpty(defaultCard)) { |
| writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_SHOW, defaultCard); |
| } |
| } |
| |
| public void addComponentToContainer(final RadContainer container, final RadComponent component, final int index) { |
| container.getDelegee().add(component.getDelegee(), component.getCustomLayoutConstraints()); |
| } |
| |
| @Override |
| public void removeComponentFromContainer(RadContainer container, RadComponent component) { |
| if (component.getId().equals(DefaultCardProperty.INSTANCE.getValue(container))) { |
| DefaultCardProperty.INSTANCE.setValueEx(container, null); |
| } |
| super.removeComponentFromContainer(container, component); |
| } |
| |
| @Override public void changeContainerLayout(RadContainer container) throws IncorrectOperationException { |
| if (container.getComponentCount() != 0) { |
| throw new IncorrectOperationException("Only empty containers can be changed to CardLayout"); |
| } |
| super.changeContainerLayout(container); |
| } |
| |
| @Override @NotNull |
| public ComponentDropLocation getDropLocation(RadContainer container, @Nullable final Point location) { |
| return new CardDropLocation(container); |
| } |
| |
| @Override |
| public Property[] getContainerProperties(final Project project) { |
| return new Property[]{ |
| HGapProperty.getInstance(project), |
| VGapProperty.getInstance(project), |
| DefaultCardProperty.INSTANCE }; |
| } |
| |
| @Override |
| public Property[] getComponentProperties(final Project project, final RadComponent component) { |
| return new Property[] { CardNameProperty.INSTANCE }; |
| } |
| |
| @Override |
| public boolean isSwitchedToChild(RadContainer container, RadComponent child) { |
| return child.getDelegee().isVisible(); |
| } |
| |
| @Override |
| public boolean switchContainerToChild(RadContainer container, RadComponent child) { |
| CardLayout cardLayout = (CardLayout) container.getLayout(); |
| String card = (String) child.getCustomLayoutConstraints(); |
| cardLayout.show(container.getDelegee(), card); |
| return true; |
| } |
| |
| @Override |
| public boolean areChildrenExclusive() { |
| return true; |
| } |
| |
| @Override public void createSnapshotLayout(final SnapshotContext context, |
| final JComponent parent, |
| final RadContainer container, |
| final LayoutManager layout) { |
| CardLayout cardLayout = (CardLayout) layout; |
| container.setLayout(new CardLayout(cardLayout.getHgap(), cardLayout.getVgap())); |
| } |
| |
| |
| @SuppressWarnings({"UseOfObsoleteCollectionType"}) |
| @Override |
| public void addSnapshotComponent(final JComponent parent, |
| final JComponent child, |
| final RadContainer container, |
| final RadComponent component) { |
| // unfortunately card can be extracted only through reflection |
| String cardName = null; |
| try { |
| final LayoutManager layout = parent.getLayout(); |
| Field vectorField = layout.getClass().getDeclaredField("vector"); |
| vectorField.setAccessible(true); |
| Vector vector = (Vector) vectorField.get(parent.getLayout()); |
| for (Object card : vector) { |
| Field nameField = card.getClass().getDeclaredField("name"); |
| nameField.setAccessible(true); |
| Field compField = card.getClass().getDeclaredField("comp"); |
| compField.setAccessible(true); |
| if (compField.get(card) == child) { |
| cardName = (String) nameField.get(card); |
| break; |
| } |
| } |
| } |
| catch (Exception e) { |
| // ignore |
| } |
| |
| if (cardName != null) { |
| component.setCustomLayoutConstraints(cardName); |
| container.addComponent(component); |
| } |
| } |
| |
| private static class CardDropLocation implements ComponentDropLocation { |
| private final RadContainer myContainer; |
| @NonNls private static final String CARD_NAME_PREFIX = "Card"; |
| |
| public CardDropLocation(final RadContainer container) { |
| myContainer = container; |
| } |
| |
| public RadContainer getContainer() { |
| return myContainer; |
| } |
| |
| public boolean canDrop(ComponentDragObject dragObject) { |
| return dragObject.getComponentCount() == 1; |
| } |
| |
| public void placeFeedback(FeedbackLayer feedbackLayer, ComponentDragObject dragObject) { |
| Rectangle rc = myContainer.getBounds(); |
| feedbackLayer.putFeedback(myContainer.getParent().getDelegee(), rc, null); |
| } |
| |
| public void processDrop(GuiEditor editor, |
| RadComponent[] components, |
| GridConstraints[] constraintsToAdjust, |
| ComponentDragObject dragObject) { |
| int cardIndex = 1; |
| while(myContainer.findComponentWithConstraints(CARD_NAME_PREFIX + cardIndex) != null) { |
| cardIndex++; |
| } |
| components [0].setCustomLayoutConstraints(CARD_NAME_PREFIX + cardIndex); |
| myContainer.addComponent(components [0]); |
| } |
| |
| @Nullable |
| public ComponentDropLocation getAdjacentLocation(Direction direction) { |
| return null; |
| } |
| } |
| |
| private static class CardNameProperty extends Property<RadComponent, String> { |
| private final LabelPropertyRenderer<String> myRenderer = new LabelPropertyRenderer<String>(); |
| |
| private final AbstractTextFieldEditor<String> myEditor = new AbstractTextFieldEditor<String>() { |
| protected void setValueFromComponent(RadComponent component, String value) { |
| myTf.setText((String) component.getCustomLayoutConstraints()); |
| } |
| |
| public String getValue() throws Exception { |
| return myTf.getText(); |
| } |
| }; |
| |
| static CardNameProperty INSTANCE = new CardNameProperty(); |
| |
| private CardNameProperty() { |
| super(null, "Card Name"); |
| } |
| |
| public String getValue(final RadComponent component) { |
| return (String) component.getCustomLayoutConstraints(); |
| } |
| |
| protected void setValueImpl(final RadComponent component, final String value) throws Exception { |
| if (!value.equals(component.getCustomLayoutConstraints())) { |
| if (component.getParent().findComponentWithConstraints(value) != null) { |
| throw new Exception(UIDesignerBundle.message("error.card.already.exists", value)); |
| } |
| component.changeCustomLayoutConstraints(value); |
| final JComponent parent = component.getParent().getDelegee(); |
| CardLayout layout = (CardLayout) parent.getLayout(); |
| layout.show(parent, value); |
| } |
| } |
| |
| @NotNull |
| public PropertyRenderer<String> getRenderer() { |
| return myRenderer; |
| } |
| |
| public PropertyEditor<String> getEditor() { |
| return myEditor; |
| } |
| |
| @Override |
| public boolean appliesToSelection(final List<RadComponent> selection) { |
| return selection.size() == 1; |
| } |
| } |
| |
| private static class DefaultCardProperty extends Property<RadContainer, String> { |
| @NonNls private static final String NAME = "Default Card"; |
| |
| private final ComponentRenderer myRenderer = new ComponentRenderer(); |
| private ComponentEditor myEditor; |
| |
| static DefaultCardProperty INSTANCE = new DefaultCardProperty(); |
| |
| public DefaultCardProperty() { |
| super(null, NAME); |
| } |
| |
| @NotNull |
| @Override |
| public PropertyRenderer<String> getRenderer() { |
| return myRenderer; |
| } |
| |
| @Override |
| public PropertyEditor<String> getEditor() { |
| if (myEditor == null) { |
| myEditor = new ComponentEditor(null, null) { |
| @Override |
| protected RadComponent[] collectFilteredComponents(RadComponent component) { |
| RadContainer container = (RadContainer)component; |
| RadComponent[] result = new RadComponent[container.getComponentCount() + 1]; |
| for (int i = 1; i < result.length; i++) { |
| result[i] = container.getComponent(i - 1); |
| } |
| return result; |
| } |
| }; |
| } |
| return myEditor; |
| } |
| |
| @Override |
| public String getValue(RadContainer component) { |
| return (String)component.getDelegee().getClientProperty(NAME); |
| } |
| |
| @Override |
| protected void setValueImpl(RadContainer component, String value) throws Exception { |
| component.getDelegee().putClientProperty(NAME, StringUtil.isEmpty(value) ? null : value); |
| } |
| |
| @Override |
| public boolean appliesToSelection(List<RadComponent> selection) { |
| return selection.size() == 1; |
| } |
| } |
| } |