CaptionPanel

This commit is contained in:
Alexander Lobas
2012-04-13 22:25:25 +04:00
parent 295e06003f
commit b4d95e313b
17 changed files with 363 additions and 72 deletions
@@ -359,6 +359,8 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
myParseTime = false;
myLayeredPane.revalidate();
myHorizontalCaption.update();
myVerticalCaption.update();
DesignerToolWindowManager.getInstance(getProject()).refresh(updateProperties);
}
@@ -65,11 +65,8 @@ public class AndroidPasteFactory implements ComponentPasteFactory {
RadViewComponent component = ModelParser.createComponent(null, metaModel);
component.setClientProperty(KEY, element.getChild("properties"));
List<RadComponent> children = component.getChildren();
for (Object childElement : element.getChildren("component")) {
RadComponent childComponent = createComponent((Element)childElement);
childComponent.setParent(component);
children.add(childComponent);
component.add(createComponent((Element)childElement), null);
}
return component;
@@ -0,0 +1,41 @@
/*
* 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.android.designer.designSurface.layout;
import com.intellij.designer.designSurface.DecorationLayer;
import com.intellij.designer.designSurface.StaticDecorator;
import com.intellij.designer.model.RadComponent;
import com.intellij.ui.LightColors;
import java.awt.*;
/**
* @author Alexander Lobas
*/
public class CaptionStaticDecorator extends StaticDecorator {
public CaptionStaticDecorator(RadComponent component) {
super(component);
}
@Override
protected void paint(DecorationLayer layer, Graphics2D g, RadComponent component) {
Rectangle bounds = component.getBounds(layer);
g.setColor(LightColors.GREEN);
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
g.setColor(Color.black);
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
@@ -97,12 +97,9 @@ public class ModelParser extends XmlRecursiveElementVisitor {
if (myRootComponent == null) {
myRootComponent = component;
}
component.setParent(myComponent);
if (myComponent != null) {
myComponent.getChildren().add(component);
myComponent.add(component, null);
}
myComponent = component;
super.visitXmlTag(tag);
myComponent = (RadViewComponent)component.getParent();
@@ -138,16 +135,8 @@ public class ModelParser extends XmlRecursiveElementVisitor {
final RadViewComponent movedComponent,
@Nullable final RadViewComponent insertBefore)
throws Exception {
movedComponent.getParent().getChildren().remove(movedComponent);
movedComponent.setParent(container);
List<RadComponent> children = container.getChildren();
if (insertBefore == null) {
children.add(movedComponent);
}
else {
children.add(children.indexOf(insertBefore), movedComponent);
}
movedComponent.removeFromParent();
container.add(movedComponent, insertBefore);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -179,15 +168,7 @@ public class ModelParser extends XmlRecursiveElementVisitor {
public static void addComponent(RadViewComponent container, final RadViewComponent newComponent, @Nullable RadViewComponent insertBefore)
throws Exception {
newComponent.setParent(container);
List<RadComponent> children = container.getChildren();
if (insertBefore == null) {
children.add(newComponent);
}
else {
children.add(children.indexOf(insertBefore), newComponent);
}
container.add(newComponent, insertBefore);
addComponentTag(container.getTag(), newComponent, insertBefore == null ? null : insertBefore.getTag(), new Computable<String>() {
@Override
@@ -202,15 +183,7 @@ public class ModelParser extends XmlRecursiveElementVisitor {
public static void pasteComponent(RadViewComponent container, RadViewComponent newComponent, @Nullable RadViewComponent insertBefore)
throws Exception {
newComponent.setParent(container);
List<RadComponent> children = container.getChildren();
if (insertBefore == null) {
children.add(newComponent);
}
else {
children.add(children.indexOf(insertBefore), newComponent);
}
container.add(newComponent, insertBefore);
PropertyParser propertyParser = container.getRoot().getClientProperty(PropertyParser.KEY);
pasteComponent(newComponent, container.getTag(), insertBefore == null ? null : insertBefore.getTag(), propertyParser);
@@ -351,8 +324,7 @@ public class ModelParser extends XmlRecursiveElementVisitor {
else if (session.getRootViews().size() == 1) {
RadViewComponent rootComponent = myRootComponent;
myRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("<root>"));
myRootComponent.getChildren().add(rootComponent);
rootComponent.setParent(myRootComponent);
myRootComponent.add(rootComponent, null);
}
updateRootComponent(myRootComponent, session, nativeComponent);
@@ -26,6 +26,7 @@ import com.intellij.util.containers.hash.HashMap;
import org.jdom.Element;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -33,11 +34,17 @@ import java.util.Map;
* @author Alexander Lobas
*/
public class RadViewComponent extends RadVisualComponent {
private final List<RadComponent> myChildren = new ArrayList<RadComponent>();
protected ViewInfo myViewInfo;
private Rectangle myMargins;
private XmlTag myTag;
private List<Property> myProperties;
@Override
public List<RadComponent> getChildren() {
return myChildren;
}
public XmlTag getTag() {
return myTag;
}
@@ -76,7 +83,7 @@ public class RadViewComponent extends RadVisualComponent {
@Override
public void delete() throws Exception {
getParent().getChildren().remove(this);
removeFromParent();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -16,8 +16,10 @@
package com.intellij.android.designer.model;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.ICaption;
import com.intellij.designer.designSurface.StaticDecorator;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import javax.swing.*;
@@ -45,4 +47,10 @@ public class RadViewContainer extends RadViewComponent {
layout.addContainerSelectionActions(designer, actionGroup, shortcuts, selection);
}
}
@Override
public ICaption getCaption() {
RadLayout layout = getLayout();
return layout == null ? null : layout.getCaption(this);
}
}
@@ -0,0 +1,61 @@
/*
* 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.android.designer.model.table;
import com.intellij.android.designer.designSurface.layout.CaptionStaticDecorator;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.StaticDecorator;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadVisualComponent;
import java.awt.*;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class RadCaptionTableColumn extends RadVisualComponent {
private final RadTableLayoutComponent myContainer;
private final int myColumnOffset;
private final int myColumnWidth;
private final StaticDecorator myDecorator = new CaptionStaticDecorator(this);
public RadCaptionTableColumn(RadTableLayoutComponent container, int columnOffset, int columnWidth, EditableArea mainArea) {
myContainer = container;
myColumnOffset = columnOffset;
myColumnWidth = columnWidth;
setNativeComponent(container.getNativeComponent());
}
@Override
public Rectangle getBounds() {
Rectangle bounds = myContainer.getBounds();
return new Rectangle(bounds.x + myColumnOffset, 3, myColumnWidth, 10);
}
@Override
public Rectangle getBounds(Component relativeTo) {
Rectangle bounds = super.getBounds(relativeTo);
bounds.y = 3;
bounds.height = 10;
return bounds;
}
@Override
public void addStaticDecorators(List<StaticDecorator> decorators, List<RadComponent> selection) {
decorators.add(myDecorator);
}
}
@@ -0,0 +1,58 @@
/*
* 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.android.designer.model.table;
import com.intellij.android.designer.designSurface.layout.CaptionStaticDecorator;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.StaticDecorator;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadVisualComponent;
import java.awt.*;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class RadCaptionTableRow extends RadVisualComponent {
private final RadViewComponent myComponent;
private final StaticDecorator myDecorator = new CaptionStaticDecorator(this);
public RadCaptionTableRow(RadTableLayoutComponent container, RadViewComponent component, EditableArea mainArea) {
myComponent = component;
setNativeComponent(container.getNativeComponent());
}
@Override
public Rectangle getBounds() {
Rectangle bounds = myComponent.getBounds();
return new Rectangle(3, bounds.y, 10, bounds.height);
}
@Override
public Rectangle getBounds(Component relativeTo) {
Rectangle bounds = super.getBounds(relativeTo);
bounds.x = 3;
bounds.width = 10;
return bounds;
}
@Override
public void addStaticDecorators(List<StaticDecorator> decorators, List<RadComponent> selection) {
decorators.add(myDecorator);
}
}
@@ -17,19 +17,23 @@ package com.intellij.android.designer.model.table;
import com.intellij.android.designer.designSurface.TreeDropToOperation;
import com.intellij.android.designer.designSurface.layout.TableLayoutDecorator;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.android.designer.model.RadViewLayout;
import com.intellij.android.designer.model.RadViewLayoutWithData;
import com.intellij.designer.designSurface.*;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class RadTableLayout extends RadViewLayoutWithData implements ILayoutDecorator {
public class RadTableLayout extends RadViewLayoutWithData implements ILayoutDecorator, ICaption, ICaptionDecorator {
private static final String[] LAYOUT_PARAMS = {"", "LinearLayout_Layout", "ViewGroup_MarginLayout"};
private TableLayoutDecorator myGridDecorator;
@@ -104,4 +108,55 @@ public class RadTableLayout extends RadViewLayoutWithData implements ILayoutDeco
List<RadComponent> selection) {
super.addSelectionActions(designer, actionGroup, shortcuts, selection); // TODO: Auto-generated method stub
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Caption
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public ICaption getCaption(RadComponent component) {
return myContainer == component && myContainer.getParent().getLayout() instanceof ICaptionDecorator ? null : this;
}
@Override
@NotNull
public RadLayout getCaptionLayout(EditableArea mainArea, boolean horizontal) {
return RadViewLayout.INSTANCE;
}
@Override
@NotNull
public List<RadComponent> getCaptionChildren(EditableArea mainArea, boolean horizontal) {
RadTableLayoutComponent container = (RadTableLayoutComponent)myContainer;
List<RadComponent> children = container.getChildren();
List<RadComponent> components = new ArrayList<RadComponent>();
if (horizontal) {
if (children.isEmpty()) {
components.add(new RadCaptionTableColumn(container, 0, container.getBounds().width, mainArea));
}
else {
int columnOffset = 0;
for (int columnWidth : container.getColumnWidths()) {
components.add(new RadCaptionTableColumn(container, columnOffset, Math.max(columnWidth, 2), mainArea));
if (columnWidth > 0) {
columnOffset += columnWidth;
}
}
}
}
else if (children.isEmpty()) {
components.add(new RadCaptionTableRow(container, container, mainArea));
}
else {
for (RadComponent component : children) {
components.add(new RadCaptionTableRow(container, (RadViewComponent)component, mainArea));
}
}
return components;
}
}
@@ -90,4 +90,15 @@ public class RadTableRowLayout extends RadLinearLayout {
super.addSelectionActions(designer, actionGroup, shortcuts, selection);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Caption
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public ICaption getCaption(RadComponent component) {
return isTableParent() ? myContainer.getParent().getLayout().getCaption(component) : null;
}
}
@@ -34,26 +34,35 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.util.Collections;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class CaptionPanel extends JLayeredPane implements DataProvider, DeleteProvider, ComponentSelectionListener {
public class CaptionPanel extends JLayeredPane implements DataProvider, DeleteProvider {
private final boolean myHorizontal;
private final EditableArea myMainArea;
private final EditableArea myArea;
private final DecorationLayer myDecorationLayer;
private final FeedbackLayer myFeedbackLayer;
private final CommonEditActionsProvider myActionsProvider;
private final RadVisualComponent myRootComponent;
private List<RadComponent> myRootChildren = Collections.emptyList();
public CaptionPanel(DesignerEditorPanel designer, boolean horizontal) {
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;
@@ -123,7 +132,12 @@ public class CaptionPanel extends JLayeredPane implements DataProvider, DeletePr
}
};
designer.getSurfaceArea().addSelectionListener(this);
myMainArea.addSelectionListener(new ComponentSelectionListener() {
@Override
public void selectionChanged(EditableArea area) {
update();
}
});
}
public void attachToScrollPane(JScrollPane scrollPane) {
@@ -169,35 +183,34 @@ public class CaptionPanel extends JLayeredPane implements DataProvider, DeletePr
myActionsProvider.deleteElement(dataContext);
}
@Override
public void selectionChanged(EditableArea area) {
List<RadComponent> selection = area.getSelection();
public void update() {
List<RadComponent> selection = myMainArea.getSelection();
if (selection.size() != 1) {
return;
}
List<RadComponent> children = myRootComponent.getChildren();
boolean update = !children.isEmpty();
boolean update = !myRootChildren.isEmpty();
children.clear();
myRootComponent.setLayout(null);
ICaption caption = null;
RadComponent component = selection.get(0);
RadComponent parent = component.getParent();
if (parent != null && parent.getLayout() instanceof ICaption) {
caption = (ICaption)parent.getLayout();
if (parent != null) {
caption = parent.getLayout().getCaption(component);
}
if (caption == null) {
caption = component.getCaption();
}
if (caption == null && component instanceof ICaption) {
caption = (ICaption)component;
if (caption == null) {
myRootChildren = Collections.emptyList();
}
if (caption != null) {
myRootComponent.setLayout(caption.getCaptionLayout(area, myHorizontal));
caption.addCaptionChildren(area, myHorizontal, children);
update = true;
else {
myRootComponent.setLayout(caption.getCaptionLayout(myMainArea, myHorizontal));
myRootChildren = caption.getCaptionChildren(myMainArea, myHorizontal);
update |= !myRootChildren.isEmpty();
}
if (update) {
@@ -89,8 +89,8 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
protected DesignerActionPanel myActionPanel;
private CaptionPanel myHorizontalCaption;
private CaptionPanel myVerticalCaption;
protected CaptionPanel myHorizontalCaption;
protected CaptionPanel myVerticalCaption;
private JScrollPane myScrollPane;
protected JLayeredPane myLayeredPane;
@@ -292,6 +292,8 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
myErrorMessages.removeAll();
myErrorStack.setText(null);
myLayeredPane.revalidate();
myHorizontalCaption.update();
myVerticalCaption.update();
myLayout.show(this, DESIGNER_CARD);
}
@@ -17,6 +17,7 @@ package com.intellij.designer.designSurface;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -24,7 +25,9 @@ import java.util.List;
* @author Alexander Lobas
*/
public interface ICaption {
@NotNull
RadLayout getCaptionLayout(EditableArea mainArea, boolean horizontal);
void addCaptionChildren(EditableArea mainArea, boolean horizontal, List<RadComponent> children);
@NotNull
List<RadComponent> getCaptionChildren(EditableArea mainArea, boolean horizontal);
}
@@ -0,0 +1,22 @@
/*
* 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;
/**
* @author Alexander Lobas
*/
public interface ICaptionDecorator {
}
@@ -16,6 +16,7 @@
package com.intellij.designer.model;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.ICaption;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.StaticDecorator;
import com.intellij.designer.designSurface.tools.DragTracker;
@@ -80,6 +81,37 @@ public abstract class RadComponent {
return getChildren().toArray();
}
public void add(@NotNull RadComponent component, @Nullable RadComponent insertBefore) {
component.setParent(this);
int index;
List<RadComponent> children = getChildren();
if (insertBefore == null) {
index = children.size();
children.add(component);
}
else {
index = children.indexOf(insertBefore);
children.add(index, component);
}
if (myLayout != null) {
myLayout.addComponentToContainer(component, index);
}
}
public void remove(@NotNull RadComponent component) {
getChildren().remove(component);
if (myLayout != null) {
myLayout.removeComponentFromContainer(component);
}
}
public void removeFromParent() {
getParent().remove(this);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Visual
@@ -113,6 +145,11 @@ public abstract class RadComponent {
JComponent shortcuts,
List<RadComponent> selection) {
}
@Nullable
public ICaption getCaption() {
return null;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Layout
@@ -32,6 +32,12 @@ public abstract class RadLayout {
myContainer = container;
}
public void addComponentToContainer(RadComponent component, int index) {
}
public void removeComponentFromContainer(RadComponent component) {
}
public abstract ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection);
@Nullable
@@ -47,4 +53,9 @@ public abstract class RadLayout {
JComponent shortcuts,
List<RadComponent> selection) {
}
@Nullable
public ICaption getCaption(RadComponent component) {
return null;
}
}
@@ -17,23 +17,14 @@ package com.intellij.designer.model;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class RadVisualComponent extends RadComponent {
protected final List<RadComponent> myChildren = new ArrayList<RadComponent>();
private Component myNativeComponent;
private final Rectangle myBounds = new Rectangle();
@Override
public List<RadComponent> getChildren() {
return myChildren;
}
@Override
public Rectangle getBounds() {
return myBounds;
@@ -42,8 +33,8 @@ public abstract class RadVisualComponent extends RadComponent {
@Override
public Rectangle getBounds(Component relativeTo) {
return myNativeComponent == relativeTo
? new Rectangle(myBounds) :
SwingUtilities.convertRectangle(myNativeComponent, myBounds, relativeTo);
? new Rectangle(getBounds()) :
SwingUtilities.convertRectangle(myNativeComponent, getBounds(), relativeTo);
}
public void setBounds(int x, int y, int width, int height) {
@@ -53,7 +44,7 @@ public abstract class RadVisualComponent extends RadComponent {
@Override
public Point convertPoint(Component relativeFrom, int x, int y) {
return myNativeComponent == relativeFrom
? myBounds.getLocation() :
? new Point(x, y) :
SwingUtilities.convertPoint(relativeFrom, x, y, myNativeComponent);
}