blob: 50faa6509b023d743021d85047c3c48d6b235c3a [file] [log] [blame]
/*
* 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;
}
}
}