| /* |
| * 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.uiDesigner.ModuleProvider; |
| 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.*; |
| import com.intellij.uiDesigner.lw.LwSplitPane; |
| import com.intellij.uiDesigner.palette.Palette; |
| import com.intellij.uiDesigner.snapShooter.SnapshotContext; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.MouseEvent; |
| |
| /** |
| * @author Anton Katilin |
| * @author Vladimir Kondratyev |
| */ |
| public final class RadSplitPane extends RadContainer { |
| public static class Factory extends RadComponentFactory { |
| public RadComponent newInstance(ModuleProvider module, Class aClass, String id) { |
| return new RadSplitPane(module, aClass, id); |
| } |
| |
| public RadComponent newInstance(final Class componentClass, final String id, final Palette palette) { |
| return new RadSplitPane(componentClass, id, palette); |
| } |
| } |
| |
| public RadSplitPane(final ModuleProvider module, final Class componentClass, final String id) { |
| super(module, componentClass, id); |
| } |
| |
| public RadSplitPane(Class componentClass, @NotNull final String id, final Palette palette) { |
| super(componentClass, id, palette); |
| } |
| |
| @Override protected RadLayoutManager createInitialLayoutManager() { |
| return new RadSplitPaneLayoutManager(); |
| } |
| |
| private static boolean isEmptySplitComponent(final Component component) { |
| return component == null || ((JComponent)component).getClientProperty(CLIENT_PROP_RAD_COMPONENT) == null; |
| } |
| |
| private boolean isLeft(Point pnt) { |
| if (getSplitPane().getOrientation() == JSplitPane.VERTICAL_SPLIT) { |
| return pnt.y < getDividerPos(); |
| } |
| else { |
| return pnt.x < getDividerPos(); |
| } |
| } |
| |
| private int getDividerPos() { |
| final JSplitPane splitPane = getSplitPane(); |
| int size = splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT ? splitPane.getHeight() : splitPane.getWidth(); |
| if (splitPane.getDividerLocation() > splitPane.getDividerSize() && |
| splitPane.getDividerLocation() < size - splitPane.getDividerSize()) { |
| return splitPane.getDividerLocation() + splitPane.getDividerSize() / 2; |
| } |
| else { |
| return size / 2; |
| } |
| } |
| |
| private JSplitPane getSplitPane() { |
| return (JSplitPane)getDelegee(); |
| } |
| |
| @Override @Nullable |
| public EventProcessor getEventProcessor(final MouseEvent event) { |
| final JSplitPane splitPane = getSplitPane(); |
| Point pnt = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), splitPane); |
| int pos = (splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT) ? pnt.y : pnt.x; |
| if (event.getID() == MouseEvent.MOUSE_PRESSED && |
| pos >= splitPane.getDividerLocation() && |
| pos < splitPane.getDividerLocation() + splitPane.getDividerSize()) { |
| return new DividerDragProcessor(); |
| } |
| return null; |
| } |
| |
| public void write(final XmlWriter writer) { |
| writer.startElement(UIFormXmlConstants.ELEMENT_SPLITPANE); |
| try { |
| writeId(writer); |
| writeClassIfDifferent(writer, JSplitPane.class.getName()); |
| writeBinding(writer); |
| |
| // Constraints and properties |
| writeConstraints(writer); |
| writeProperties(writer); |
| |
| // Margin and border |
| writeBorder(writer); |
| writeChildren(writer); |
| } |
| finally { |
| writer.endElement(); // scrollpane |
| } |
| } |
| |
| |
| @Override |
| protected void importSnapshotComponent(final SnapshotContext context, final JComponent component) { |
| JSplitPane splitPane = (JSplitPane) component; |
| importSideComponent(splitPane.getLeftComponent(), context, LwSplitPane.POSITION_LEFT); |
| importSideComponent(splitPane.getRightComponent(), context, LwSplitPane.POSITION_RIGHT); |
| } |
| |
| private void importSideComponent(final Component sideComponent, |
| final SnapshotContext context, |
| final String position) { |
| if (sideComponent instanceof JComponent) { |
| RadComponent radSideComponent = createSnapshotComponent(context, (JComponent) sideComponent); |
| if (radSideComponent != null) { |
| radSideComponent.setCustomLayoutConstraints(position); |
| addComponent(radSideComponent); |
| } |
| } |
| } |
| |
| private class RadSplitPaneLayoutManager extends RadLayoutManager { |
| |
| @Nullable public String getName() { |
| return null; |
| } |
| |
| public void writeChildConstraints(final XmlWriter writer, final RadComponent child) { |
| writer.startElement("splitpane"); |
| try { |
| final String position = (String)child.getCustomLayoutConstraints(); |
| if (!LwSplitPane.POSITION_LEFT.equals(position) && !LwSplitPane.POSITION_RIGHT.equals(position)) { |
| throw new IllegalStateException("invalid position: " + position); |
| } |
| writer.addAttribute("position", position); |
| } |
| finally { |
| writer.endElement(); |
| } |
| } |
| |
| public void addComponentToContainer(final RadContainer container, final RadComponent component, final int index) { |
| final JSplitPane splitPane = (JSplitPane) container.getDelegee(); |
| final JComponent delegee = component.getDelegee(); |
| if (LwSplitPane.POSITION_LEFT.equals(component.getCustomLayoutConstraints())) { |
| splitPane.setLeftComponent(delegee); |
| } |
| else if (LwSplitPane.POSITION_RIGHT.equals(component.getCustomLayoutConstraints())) { |
| splitPane.setRightComponent(delegee); |
| } |
| else { |
| throw new IllegalStateException("invalid layout constraints on component added to RadSplitPane"); |
| } |
| } |
| |
| @Override @NotNull |
| public ComponentDropLocation getDropLocation(RadContainer container, @Nullable final Point location) { |
| if (location == null) { |
| return new MyDropLocation(isEmptySplitComponent(getSplitPane().getLeftComponent())); |
| } |
| return new MyDropLocation(isLeft(location)); |
| } |
| } |
| |
| private class MyDropLocation implements ComponentDropLocation { |
| private final boolean myLeft; |
| |
| public MyDropLocation(final boolean left) { |
| myLeft = left; |
| } |
| |
| public RadContainer getContainer() { |
| return RadSplitPane.this; |
| } |
| |
| public boolean canDrop(ComponentDragObject dragObject) { |
| /* |
| TODO[yole]: support multi-drop (is it necessary?) |
| if (componentCount == 2) { |
| return isEmptySplitComponent(getSplitPane().getLeftComponent()) && |
| isEmptySplitComponent(getSplitPane().getRightComponent()); |
| } |
| */ |
| return dragObject.getComponentCount() == 1 && |
| isEmptySplitComponent(myLeft ? getSplitPane().getLeftComponent() : getSplitPane().getRightComponent()); |
| } |
| |
| public void placeFeedback(FeedbackLayer feedbackLayer, ComponentDragObject dragObject) { |
| final JSplitPane splitPane = getSplitPane(); |
| int dividerPos = getDividerPos(); |
| int dividerStartPos = dividerPos - splitPane.getDividerSize()/2; |
| int dividerEndPos = dividerPos + splitPane.getDividerSize() - splitPane.getDividerSize()/2; |
| Rectangle rc; |
| if (splitPane.getOrientation() == JSplitPane.VERTICAL_SPLIT) { |
| rc = myLeft |
| ? new Rectangle(0, 0, getWidth(), dividerStartPos) |
| : new Rectangle(0, dividerEndPos, getWidth(), getHeight() - dividerEndPos); |
| } |
| else { |
| rc = myLeft |
| ? new Rectangle(0, 0, dividerStartPos, getHeight()) |
| : new Rectangle(dividerEndPos, 0, getWidth() - dividerEndPos, getHeight()); |
| } |
| feedbackLayer.putFeedback(getDelegee(), rc, getInsertFeedbackTooltip()); |
| } |
| |
| private String getInsertFeedbackTooltip() { |
| String pos; |
| if (getSplitPane().getOrientation() == JSplitPane.VERTICAL_SPLIT) { |
| pos = myLeft ? UIDesignerBundle.message("insert.feedback.top") : UIDesignerBundle.message("insert.feedback.bottom"); |
| } |
| else { |
| pos = myLeft ? UIDesignerBundle.message("insert.feedback.left") : UIDesignerBundle.message("insert.feedback.right"); |
| } |
| return getDisplayName() + " (" + pos + ")"; |
| } |
| |
| public void processDrop(GuiEditor editor, |
| RadComponent[] components, |
| GridConstraints[] constraintsToAdjust, |
| ComponentDragObject dragObject) { |
| components[0].setCustomLayoutConstraints(myLeft ? LwSplitPane.POSITION_LEFT : LwSplitPane.POSITION_RIGHT); |
| addComponent(components[0]); |
| } |
| |
| @Nullable |
| public ComponentDropLocation getAdjacentLocation(Direction direction) { |
| return null; |
| } |
| } |
| |
| private class DividerDragProcessor extends EventProcessor { |
| protected void processKeyEvent(KeyEvent e) { |
| } |
| |
| protected void processMouseEvent(MouseEvent event) { |
| JSplitPane splitPane = getSplitPane(); |
| Point pnt = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), splitPane); |
| splitPane.dispatchEvent(new MouseEvent(splitPane, event.getID(), event.getWhen(), event.getModifiers(), pnt.x, pnt.y, |
| event.getClickCount(), event.isPopupTrigger(), event.getButton())); |
| } |
| |
| @Override public boolean needMousePressed() { |
| return true; |
| } |
| |
| protected boolean cancelOperation() { |
| return false; |
| } |
| } |
| } |