This commit is contained in:
Alexander Lobas
2012-02-25 22:32:25 +04:00
parent dfae35f193
commit 087580afb0
24 changed files with 877 additions and 87 deletions
@@ -34,20 +34,24 @@ import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.selection.DirectionResizePoint;
import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator;
import com.intellij.designer.designSurface.tools.ComponentCreationFactory;
import com.intellij.designer.designSurface.tools.CreationTool;
import com.intellij.designer.designSurface.tools.ComponentPasteFactory;
import com.intellij.designer.model.MetaManager;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.palette.Item;
import com.intellij.designer.utils.Position;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.uipreview.*;
@@ -56,9 +60,8 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
@@ -74,10 +77,19 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
public AndroidDesignerEditorPanel(@NotNull Module module, @NotNull VirtualFile file) {
super(module, file);
myActionPanel.getActionGroup()
.add(new AnAction("Android", "Description", IconLoader.getIcon("/com/intellij/android/designer/icons/DeviceScreen.png")) {
@Override
public void actionPerformed(AnActionEvent e) {
System.out.println("Action: " + e);
}
});
myActionPanel.update();
myXmlFile = (XmlFile)ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
@Override
public PsiFile compute() {
return PsiManager.getInstance(myModule.getProject()).findFile(myFile);
return PsiManager.getInstance(getProject()).findFile(myFile);
}
});
@@ -111,7 +123,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
showDesignerCard();
myLayeredPane.repaint();
DesignerToolWindowManager.getInstance(myModule.getProject()).refresh();
DesignerToolWindowManager.getInstance(getProject()).refresh();
}
catch (Throwable e) {
showError("Parse error: ", e);
@@ -120,7 +132,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
private void parseFile() throws Throwable {
final RadViewComponent[] rootComponents = new RadViewComponent[1];
final MetaManager metaManager = ViewsMetaManager.getInstance(myModule.getProject());
final MetaManager metaManager = ViewsMetaManager.getInstance(getProject());
final String layoutXmlText = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
RadViewComponent myComponent;
@@ -188,7 +200,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
int size = views.size();
if (size == 1) {
RadViewComponent newRootComponent = new RadViewComponent(null);
newRootComponent.setMetaModel(ViewsMetaManager.getInstance(myModule.getProject()).getModelByTag("<root>"));
newRootComponent.setMetaModel(ViewsMetaManager.getInstance(getProject()).getModelByTag("<root>"));
newRootComponent.getChildren().add(rootComponent);
rootComponent.setParent(newRootComponent);
@@ -252,7 +264,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
ThemeData theme = new ThemeData("Theme", false);
return RenderUtil.createRenderSession(myModule.getProject(), layoutXmlText, myFile, target, facet, config, xdpi, ydpi, theme);
return RenderUtil.createRenderSession(getProject(), layoutXmlText, myFile, target, facet, config, xdpi, ydpi, theme);
}
}).get();
}
@@ -270,6 +282,11 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
mySession = null;
}
@Override
public String getPlatformTarget() {
return "android";
}
@Override
public TreeComponentDecorator getTreeDecorator() {
return myTreeDecorator;
@@ -287,6 +304,55 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
return null;
}
@Override
@NotNull
protected ComponentCreationFactory createCreationFactory(Item paletteItem) {
return new ComponentCreationFactory() {
@Override
@NotNull
public RadComponent create() throws Exception {
return new RadViewComponent(null);
}
};
//return null; // TODO: Auto-generated method stub
}
@Override
public ComponentPasteFactory createPasteFactory(String xmlComponents) {
return new ComponentPasteFactory() {
@NotNull
@Override
public List<RadComponent> create() throws Exception {
return Collections.<RadComponent>singletonList(new RadViewComponent(null));
}
};
//return null; // TODO: Auto-generated method stub
}
@Override
protected boolean execute(ThrowableRunnable<Exception> operation) {
try {
operation.run();
return true;
}
catch (Throwable e) {
showError("Execute command", e);
return false;
}
}
@Override
protected void execute(List<EditOperation> operations) {
try {
for (EditOperation operation : operations) {
operation.execute();
}
}
catch (Throwable e) {
showError("Execute command", e);
}
}
private static class RootView extends JComponent {
private final BufferedImage myImage;
@@ -16,7 +16,12 @@
package com.intellij.android.designer.model;
import com.intellij.designer.model.RadComponent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.xml.XmlTag;
import org.jdom.Element;
import javax.swing.*;
import java.awt.*;
@@ -29,6 +34,13 @@ import java.util.List;
* @author Alexander Lobas
*/
public class RadViewComponent extends RadComponent {
public static final AnAction LinearLayout =
new AnAction("Horizontal/Vertical", "LinearLayout", IconLoader.getIcon("/com/intellij/android/designer/icons/LinearLayout.png")) {
@Override
public void actionPerformed(AnActionEvent e) {
}
};
private final List<RadComponent> myChildren = new ArrayList<RadComponent>();
private Component myNativeComponent;
private final Rectangle myBounds = new Rectangle();
@@ -81,4 +93,18 @@ public class RadViewComponent extends RadComponent {
public Point convertPoint(Component component, int x, int y) {
return SwingUtilities.convertPoint(component, x, y, myNativeComponent);
}
@Override
public void addSelectionActions(DefaultActionGroup actionGroup, JComponent shortcuts, List<RadComponent> selection) {
if (myTag != null && myTag.getName().equals("LinearLayout") && selection.size() == 1 && selection.get(0) == this) {
AnAction action = new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
System.out.println("LinearLayout: " + e);
}
};
action.copyFrom(LinearLayout);
actionGroup.add(action);
}
}
}
@@ -17,10 +17,16 @@ package com.intellij.android.designer.model;
import com.intellij.designer.designSurface.ComponentDecorator;
import com.intellij.designer.designSurface.selection.NonResizeSelectionDecorator;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import javax.swing.*;
import java.awt.*;
import java.util.List;
/**
* @author Alexander Lobas
@@ -33,7 +39,26 @@ public class RadViewLayout extends RadLayout {
}
@Override
public ComponentDecorator getChildSelectionDecorator(RadComponent component) {
public ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection) {
return new NonResizeSelectionDecorator(Color.RED, 1);
}
@Override
public void addSelectionActions(DefaultActionGroup actionGroup, JComponent shortcuts, List<RadComponent> selection) {
if (myContainer.getTag() != null && myContainer.getTag().getName().equals("LinearLayout")) {
for (RadComponent component : selection) {
if (myContainer != component.getParent()) {
return;
}
}
AnAction action = new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
System.out.println("LinearLayout: " + e);
}
};
action.copyFrom(RadViewComponent.LinearLayout);
actionGroup.add(action);
}
}
}
@@ -17,6 +17,7 @@ package com.intellij.designer;
import com.intellij.designer.componentTree.ComponentTree;
import com.intellij.designer.componentTree.ComponentTreeBuilder;
import com.intellij.designer.componentTree.TreeEditableArea;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.propertyTable.PropertyTablePanel;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
@@ -43,6 +44,7 @@ import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -56,7 +58,7 @@ public final class DesignerToolWindowManager implements ProjectComponent {
private final FileEditorManager myFileEditorManager;
private ToolWindow myToolWindow;
private ComponentTree myComponentTree;
private AbstractTreeBuilder myTreeBuilder;
private ComponentTreeBuilder myTreeBuilder;
private PropertyTablePanel myPropertyTablePanel;
private boolean myToolWindowReady;
private boolean myToolWindowDisposed;
@@ -119,6 +121,12 @@ public final class DesignerToolWindowManager implements ProjectComponent {
}
}
@Nullable
public TreeEditableArea getTreeArea() {
return myTreeBuilder == null ? null : myTreeBuilder.getTreeArea();
}
@Nullable
private static DesignerEditorPanel getDesigner(FileEditor editor) {
if (editor instanceof DesignerEditor) {
DesignerEditor designerEditor = (DesignerEditor)editor;
@@ -127,7 +135,8 @@ public final class DesignerToolWindowManager implements ProjectComponent {
return null;
}
private DesignerEditorPanel getActiveDesigner() {
@Nullable
public DesignerEditorPanel getActiveDesigner() {
FileEditor[] editors = myFileEditorManager.getSelectedEditors();
return editors.length > 0 ? getDesigner(editors[0]) : null;
}
@@ -150,10 +159,12 @@ public final class DesignerToolWindowManager implements ProjectComponent {
myComponentTree.newModel();
if (designer == null) {
myComponentTree.setDecorator(null);
myComponentTree.setActionPanel(null);
myToolWindow.setAvailable(false, null);
}
else {
myComponentTree.setDecorator(designer.getTreeDecorator());
myComponentTree.setActionPanel(designer.getActionPanel());
myTreeBuilder = new ComponentTreeBuilder(myComponentTree, designer);
myToolWindow.setAvailable(true, null);
myToolWindow.show(null);
@@ -0,0 +1,205 @@
/*
* 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.actions;
import com.intellij.designer.DesignerBundle;
import com.intellij.designer.clipboard.SerializedComponentData;
import com.intellij.designer.clipboard.SimpleTransferable;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.tools.ComponentPasteFactory;
import com.intellij.designer.designSurface.tools.PasteTool;
import com.intellij.designer.model.RadComponent;
import com.intellij.ide.CopyProvider;
import com.intellij.ide.CutProvider;
import com.intellij.ide.DeleteProvider;
import com.intellij.ide.PasteProvider;
import com.intellij.ide.dnd.FileCopyPasteUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.util.ThrowableRunnable;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class CommonEditActionsProvider implements DeleteProvider, CopyProvider, PasteProvider, CutProvider {
private static final DataFlavor DATA_FLAVOR = FileCopyPasteUtil.createJvmDataFlavor(SerializedComponentData.class);
private final DesignerEditorPanel myDesigner;
public CommonEditActionsProvider(DesignerEditorPanel designer) {
myDesigner = designer;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Delete
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean canDeleteElement(DataContext dataContext) {
// TODO: InplaceEditing
List<RadComponent> selection = myDesigner.getActionsArea().getSelection();
if (selection.isEmpty()) {
return false;
}
for (RadComponent component : selection) {
if (!component.canDelete()) {
return false;
}
}
return true;
}
@Override
public void deleteElement(DataContext dataContext) {
CommandProcessor.getInstance().executeCommand(myDesigner.getProject(), new Runnable() {
public void run() {
myDesigner.getToolProvider().execute(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
List<RadComponent> components = RadComponent.getPureSelection(myDesigner.getActionsArea().getSelection());
for (RadComponent component : components) {
component.delete();
}
}
});
}
}, DesignerBundle.message("command.delete.selection"), null);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Copy
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean isCopyVisible(DataContext dataContext) {
return true;
}
@Override
public boolean isCopyEnabled(DataContext dataContext) {
// TODO: InplaceEditing
return !myDesigner.getActionsArea().getSelection().isEmpty();
}
@Override
public void performCopy(DataContext dataContext) {
doCopy();
}
private boolean doCopy() {
return myDesigner.getToolProvider().execute(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
Element root = new Element("designer");
root.setAttribute("target", myDesigner.getPlatformTarget());
List<RadComponent> components = RadComponent.getPureSelection(myDesigner.getActionsArea().getSelection());
for (RadComponent component : components) {
component.copyTo(root);
}
SerializedComponentData data = new SerializedComponentData(new XMLOutputter().outputString(root));
CopyPasteManager.getInstance().setContents(new SimpleTransferable(data, DATA_FLAVOR));
}
});
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Paste
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean isPastePossible(DataContext dataContext) {
return isPasteEnabled(dataContext);
}
@Override
public boolean isPasteEnabled(DataContext dataContext) {
// TODO: InplaceEditing
return getSerializedComponentData() != null;
}
@Nullable
private String getSerializedComponentData() {
try {
CopyPasteManager copyPasteManager = CopyPasteManager.getInstance();
if (!copyPasteManager.isDataFlavorAvailable(DATA_FLAVOR)) {
return null;
}
Transferable content = copyPasteManager.getContents();
if (content == null) {
return null;
}
Object transferData = content.getTransferData(DATA_FLAVOR);
if (transferData instanceof SerializedComponentData) {
SerializedComponentData data = (SerializedComponentData)transferData;
String xmlComponents = data.getSerializedComponents();
if (xmlComponents.startsWith("<designer target=\"" + myDesigner.getPlatformTarget() + "\">")) {
return xmlComponents;
}
}
}
catch (Throwable e) {
}
return null;
}
@Override
public void performPaste(DataContext dataContext) {
ComponentPasteFactory factory = myDesigner.createPasteFactory(getSerializedComponentData());
if (factory != null) {
myDesigner.getToolProvider().setActiveTool(new PasteTool(true, factory));
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Cut
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean isCutVisible(DataContext dataContext) {
return true;
}
@Override
public boolean isCutEnabled(DataContext dataContext) {
return isCopyEnabled(dataContext) && canDeleteElement(dataContext);
}
@Override
public void performCut(DataContext dataContext) {
if (doCopy()) {
deleteElement(dataContext);
}
}
}
@@ -0,0 +1,130 @@
/*
* 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.actions;
import com.intellij.designer.designSurface.ComponentSelectionListener;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.model.RadComponent;
import com.intellij.openapi.actionSystem.*;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.util.List;
import java.util.Set;
/**
* @author Alexander Lobas
*/
public class DesignerActionPanel implements DataProvider {
public static final String TOOLBAR = "DesignerToolbar";
public static final String POPUP = "DesignerPopup";
private final DefaultActionGroup myActionGroup = new DefaultActionGroup();
private final DefaultActionGroup myStaticGroup = new DefaultActionGroup();
private final DefaultActionGroup myDynamicGroup = new DefaultActionGroup();
private final ActionToolbar myToolbar;
private final CommonEditActionsProvider myCommonEditActionsProvider;
private final JComponent myShortcuts;
public DesignerActionPanel(DesignerEditorPanel designer, JComponent shortcuts) {
myCommonEditActionsProvider = new CommonEditActionsProvider(designer);
myShortcuts = shortcuts;
myActionGroup.add(myStaticGroup);
myActionGroup.add(myDynamicGroup);
myToolbar = ActionManager.getInstance().createActionToolbar(TOOLBAR, myActionGroup, true);
myToolbar.setMiniMode(true);
registerAction(new SelectAllAction(designer.getSurfaceArea()), "$SelectAll");
designer.getSurfaceArea().addSelectionListener(new ComponentSelectionListener() {
@Override
public void selectionChanged(EditableArea area) {
updateSelectionActions(area.getSelection());
}
});
}
private void registerAction(AnAction action, @NonNls String actionId) {
action.registerCustomShortcutSet(
ActionManager.getInstance().getAction(actionId).getShortcutSet(),
myShortcuts
);
}
public JComponent getToolbarComponent() {
return myToolbar.getComponent();
}
public DefaultActionGroup getActionGroup() {
return myStaticGroup;
}
public void update() {
boolean isEmpty = myActionGroup.getChildrenCount() == 0;
myToolbar.updateActionsImmediately();
myToolbar.setMiniMode(isEmpty);
if (!isEmpty) {
myToolbar.getComponent().setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM));
}
}
private void updateSelectionActions(List<RadComponent> selection) {
boolean update = myDynamicGroup.getChildrenCount() > 0;
for (AnAction action : myDynamicGroup.getChildActionsOrStubs()) {
action.unregisterCustomShortcutSet(myShortcuts);
}
myDynamicGroup.removeAll();
Set<RadComponent> parents = new HashSet<RadComponent>();
for (RadComponent component : selection) {
RadComponent parent = component.getParent();
if (parent != null) {
parents.add(parent);
}
}
for (RadComponent parent : parents) {
parent.getLayout().addSelectionActions(myDynamicGroup, myShortcuts, selection);
}
for (RadComponent component : selection) {
component.addSelectionActions(myDynamicGroup, myShortcuts, selection);
}
update |= myDynamicGroup.getChildrenCount() > 0;
if (update) {
update();
}
}
@Override
public Object getData(@NonNls String dataId) {
if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId) ||
PlatformDataKeys.CUT_PROVIDER.is(dataId) ||
PlatformDataKeys.COPY_PROVIDER.is(dataId) ||
PlatformDataKeys.PASTE_PROVIDER.is(dataId)) {
return myCommonEditActionsProvider;
}
return null;
}
}
@@ -0,0 +1,51 @@
/*
* 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.actions;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadComponentVisitor;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import java.util.ArrayList;
import java.util.List;
/**
* @author Alexander Lobas
*/
public class SelectAllAction extends AnAction {
private final EditableArea myArea;
public SelectAllAction(EditableArea area) {
myArea = area;
}
@Override
public void actionPerformed(AnActionEvent e) {
RadComponent rootComponent = myArea.getRootComponent();
if (rootComponent != null) {
final List<RadComponent> components = new ArrayList<RadComponent>();
rootComponent.accept(new RadComponentVisitor() {
@Override
public void endVisit(RadComponent component) {
components.add(component);
}
}, true);
myArea.setSelection(components);
}
}
}
@@ -0,0 +1,33 @@
/*
* 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.clipboard;
/**
* This class must be in main classloader because of JVM's restrictions (it's used as DataFlavor class)
*
* @author yole
*/
public final class SerializedComponentData {
private final String mySerializedComponents;
public SerializedComponentData(String components) {
mySerializedComponents = components;
}
public String getSerializedComponents() {
return mySerializedComponents;
}
}
@@ -0,0 +1,76 @@
/*
* 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.clipboard;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
* @author yole
*/
public class SimpleTransferable implements Transferable {
private static final Logger LOG = Logger.getInstance("#com.intellij.designer.clipboard.SimpleTransferable");
private final Object myData;
private final DataFlavor myFlavor;
public SimpleTransferable(Object data, DataFlavor flavor) {
myData = data;
myFlavor = flavor;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
try {
return new DataFlavor[]{myFlavor};
}
catch (Exception ex) {
LOG.error(ex);
return new DataFlavor[0];
}
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
try {
return myFlavor.equals(flavor);
}
catch (Exception ex) {
LOG.error(ex);
return false;
}
}
@Override
@Nullable
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
try {
if (!myFlavor.equals(flavor)) {
return null;
}
return myData;
}
catch (Exception e) {
LOG.error(e);
return null;
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.designer.componentTree;
import com.intellij.designer.actions.DesignerActionPanel;
import com.intellij.designer.designSurface.FeedbackTreeLayer;
import com.intellij.designer.model.RadComponent;
import com.intellij.openapi.actionSystem.DataProvider;
@@ -37,6 +38,7 @@ import java.awt.*;
*/
public final class ComponentTree extends Tree implements DataProvider {
private TreeComponentDecorator myDecorator;
private DesignerActionPanel myActionPanel;
private RadComponent myMarkComponent;
private int myMarkFeedback;
@@ -64,11 +66,15 @@ public final class ComponentTree extends Tree implements DataProvider {
setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
}
public void setDecorator(TreeComponentDecorator decorator) {
public void setDecorator(@Nullable TreeComponentDecorator decorator) {
myDecorator = decorator;
myMarkComponent = null;
}
public void setActionPanel(@Nullable DesignerActionPanel actionPanel) {
myActionPanel = actionPanel;
}
public void mark(RadComponent component, int feedback) {
myMarkComponent = component;
myMarkFeedback = feedback;
@@ -77,7 +83,12 @@ public final class ComponentTree extends Tree implements DataProvider {
@Override
public Object getData(@NonNls String dataId) {
return null; //TODO
// TODO: support keys
if (myActionPanel != null) {
return myActionPanel.getData(dataId);
}
return null;
}
@Nullable
@@ -50,6 +50,10 @@ public final class ComponentTreeBuilder extends AbstractTreeBuilder implements C
addListeners();
}
public TreeEditableArea getTreeArea() {
return myTreeArea;
}
@Override
public void dispose() {
removeListeners();
@@ -21,6 +21,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* @author Alexander Lobas
@@ -34,8 +36,9 @@ public class DecorationLayer extends JComponent {
@Nullable
public InputTool findTargetTool(int x, int y) {
for (RadComponent component : myArea.getSelection()) {
ComponentDecorator decorator = getDecorator(component);
List<RadComponent> selection = myArea.getSelection();
for (RadComponent component : selection) {
ComponentDecorator decorator = getDecorator(component, selection);
InputTool tracker = decorator.findTargetTool(this, component, x, y);
if (tracker != null) {
return tracker;
@@ -50,17 +53,18 @@ public class DecorationLayer extends JComponent {
}
private void painSelection(Graphics2D g) {
for (RadComponent component : myArea.getSelection()) {
ComponentDecorator decorator = getDecorator(component);
List<RadComponent> selection = myArea.getSelection();
for (RadComponent component : selection) {
ComponentDecorator decorator = getDecorator(component, selection);
decorator.decorate(this, g, component);
}
}
private ComponentDecorator getDecorator(RadComponent component) {
private ComponentDecorator getDecorator(RadComponent component, List<RadComponent> selection) {
RadComponent parent = component.getParent();
if (parent == null) {
return myArea.getRootSelectionDecorator();
}
return parent.getLayout().getChildSelectionDecorator(component);
return parent.getLayout().getChildSelectionDecorator(component, selection);
}
}
@@ -16,17 +16,22 @@
package com.intellij.designer.designSurface;
import com.intellij.designer.DesignerToolWindowManager;
import com.intellij.designer.actions.DesignerActionPanel;
import com.intellij.designer.componentTree.TreeComponentDecorator;
import com.intellij.designer.designSurface.tools.InputTool;
import com.intellij.designer.designSurface.tools.SelectionTool;
import com.intellij.designer.designSurface.tools.ToolProvider;
import com.intellij.designer.componentTree.TreeEditableArea;
import com.intellij.designer.designSurface.tools.*;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadComponentVisitor;
import com.intellij.designer.palette.Item;
import com.intellij.ide.palette.PaletteItem;
import com.intellij.ide.palette.impl.PaletteManager;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.ScrollPaneFactory;
@@ -36,7 +41,10 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
/**
@@ -59,14 +67,19 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
private final CardLayout myLayout = new CardLayout();
private JPanel myDesignerCard;
protected DesignerActionPanel myActionPanel;
private CaptionPanel myHorizontalCaption;
private CaptionPanel myVerticalCaption;
private JScrollPane myScrollPane;
protected JLayeredPane myLayeredPane;
protected GlassLayer myGlassLayer;
private DecorationLayer myDecorationLayer;
private FeedbackLayer myFeedbackLayer;
private ListSelectionListener myPaletteListener;
protected ToolProvider myToolProvider;
protected EditableArea mySurfaceArea;
@@ -90,15 +103,16 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
add(myDesignerCard, DESIGNER_CARD);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.BOTH;
myVerticalCaption = new CaptionPanel(this, false);
myDesignerCard.add(myVerticalCaption, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.gridy = 1;
myHorizontalCaption = new CaptionPanel(this, true);
myDesignerCard.add(myHorizontalCaption, gbc);
@@ -149,12 +163,45 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
}
};
myPaletteListener = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (DesignerToolWindowManager.getInstance(getProject()).getActiveDesigner() == DesignerEditorPanel.this) {
Item paletteItem = (Item)PaletteManager.getInstance(getProject()).getActiveItem();
if (paletteItem != null) {
myToolProvider.setActiveTool(new CreationTool(true, createCreationFactory(paletteItem)));
}
else if (myToolProvider.getActiveTool() instanceof CreationTool) {
myToolProvider.loadDefaultTool();
}
}
}
};
myToolProvider = new ToolProvider() {
@Override
public void loadDefaultTool() {
setActiveTool(new SelectionTool());
}
@Override
public void setActiveTool(InputTool tool) {
if (getActiveTool() instanceof CreationTool && !(tool instanceof CreationTool)) {
PaletteManager.getInstance(getProject()).clearActiveItem();
}
super.setActiveTool(tool);
}
@Override
public boolean execute(ThrowableRunnable<Exception> operation) {
return DesignerEditorPanel.this.execute(operation);
}
@Override
public void execute(List<EditOperation> operations) {
DesignerEditorPanel.this.execute(operations);
}
@Override
public void showError(@NonNls String message, Throwable e) {
DesignerEditorPanel.this.showError(message, e);
@@ -171,13 +218,29 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
myLayeredPane.add(myFeedbackLayer, LAYER_FEEDBACK);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.gridy = 2;
gbc.weightx = 1;
gbc.weighty = 1;
myScrollPane = ScrollPaneFactory.createScrollPane(myLayeredPane);
myScrollPane.setBackground(Color.WHITE);
myDesignerCard.add(myScrollPane, gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
myActionPanel = new DesignerActionPanel(this, myGlassLayer);
myDesignerCard.add(myActionPanel.getToolbarComponent(), gbc);
PaletteManager.getInstance(getProject()).addSelectionListener(myPaletteListener);
}
protected final void showDesignerCard() {
myLayout.show(this, DESIGNER_CARD);
}
private void createErrorCard() {
@@ -185,33 +248,54 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
add(myErrorLabel, ERROR_CARD);
}
protected final void showDesignerCard() {
myLayout.show(this, DESIGNER_CARD);
public void showError(@NonNls String message, Throwable e) {
myRootComponent = null;
myErrorLabel.setText(message + e.toString());
myLayout.show(this, ERROR_CARD);
DesignerToolWindowManager.getInstance(getProject()).refresh();
repaint();
if (ApplicationManagerEx.getApplicationEx().isInternal()) {
e.printStackTrace();
}
}
public abstract String getPlatformTarget();
public Project getProject() {
return myModule.getProject();
}
public EditableArea getSurfaceArea() {
return mySurfaceArea;
}
public EditableArea getActionsArea() {
TreeEditableArea treeArea = DesignerToolWindowManager.getInstance(getProject()).getTreeArea();
return treeArea == null ? mySurfaceArea : treeArea;
}
public ToolProvider getToolProvider() {
return myToolProvider;
}
public DesignerActionPanel getActionPanel() {
return myActionPanel;
}
protected abstract ComponentDecorator getRootSelectionDecorator();
@Nullable
protected abstract EditOperation processRootOperation(OperationContext context);
public void showError(@NonNls String message, Throwable e) {
myRootComponent = null;
myErrorLabel.setText(message + e.toString());
myLayout.show(this, ERROR_CARD);
DesignerToolWindowManager.getInstance(myModule.getProject()).refresh();
repaint();
if (ApplicationManagerEx.getApplicationEx().isInternal()) {
e.printStackTrace();
}
}
protected abstract boolean execute(ThrowableRunnable<Exception> operation);
protected abstract void execute(List<EditOperation> operations);
@NotNull
protected abstract ComponentCreationFactory createCreationFactory(Item paletteItem);
@Nullable
public abstract ComponentPasteFactory createPasteFactory(String xmlComponents);
public void activate() {
}
@@ -221,11 +305,12 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
@Override
public Object getData(@NonNls String dataId) {
return null; //To change body of implemented methods use File | Settings | File Templates.
// TODO: support keys
return myActionPanel.getData(dataId);
}
public void dispose() {
// TODO: Auto-generated method stub
PaletteManager.getInstance(getProject()).removeSelectionListener(myPaletteListener);
}
public JComponent getPreferredFocusedComponent() {
@@ -122,14 +122,7 @@ public class DragTracker extends SelectionTracker {
myContext.setLocation(getLocation());
if (myContext.getComponents() == null) {
List<RadComponent> components = new ArrayList<RadComponent>();
List<RadComponent> selection = myArea.getSelection();
for (RadComponent component : selection) {
if (!isParentsContainedIn(selection, component)) {
components.add(component);
}
}
List<RadComponent> components = RadComponent.getPureSelection(myArea.getSelection());
RadComponent parent = null;
for (RadComponent component : components) {
@@ -148,15 +141,4 @@ public class DragTracker extends SelectionTracker {
}
}
}
private static boolean isParentsContainedIn(List<RadComponent> components, RadComponent component) {
RadComponent parent = component.getParent();
while (parent != null) {
if (components.contains(parent)) {
return true;
}
parent = parent.getParent();
}
return false;
}
}
@@ -134,15 +134,18 @@ public class MarqueeTracker extends InputTool {
private void performMarqueeSelect() {
final Rectangle selectionRectangle = getSelectionRectangle();
final List<RadComponent> newSelection = new ArrayList<RadComponent>();
RadComponent rootComponent = myArea.getRootComponent();
myArea.getRootComponent().accept(new RadComponentVisitor() {
@Override
public void endVisit(RadComponent component) {
if (selectionRectangle.contains(component.getBounds(myArea.getNativeComponent()))) {
newSelection.add(component);
if (rootComponent != null) {
rootComponent.accept(new RadComponentVisitor() {
@Override
public void endVisit(RadComponent component) {
if (selectionRectangle.contains(component.getBounds(myArea.getNativeComponent()))) {
newSelection.add(component);
}
}
}
}, true);
}, true);
}
if (mySelectionMode == TOGGLE_MODE) {
List<RadComponent> selection = new ArrayList<RadComponent>(myArea.getSelection());
@@ -116,16 +116,13 @@ public class ResizeTracker extends InputTool {
private void executeCommand() {
if (myExecuteEnabled) {
try {
for (EditOperation operation : getOperations()) {
if (operation.canExecute()) {
operation.execute();
}
List<EditOperation> operations = new ArrayList<EditOperation>();
for (EditOperation operation : getOperations()) {
if (operation.canExecute()) {
operations.add(operation);
}
}
catch (Exception e) {
myToolProvider.showError("Execute command: ", e);
}
myToolProvider.execute(operations);
}
}
@@ -22,6 +22,8 @@ import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
/**
* @author Alexander Lobas
*/
@@ -76,12 +78,7 @@ public abstract class TargetingTool extends InputTool {
protected void executeCommand() {
if (myExecuteEnabled) {
try {
myTargetOperation.execute();
}
catch (Exception e) {
myToolProvider.showError("Execute command: ", e);
}
myToolProvider.execute(Collections.singletonList(myTargetOperation));
}
}
@@ -15,12 +15,15 @@
*/
package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.List;
/**
* @author Alexander Lobas
@@ -126,4 +129,8 @@ public abstract class ToolProvider {
}
public abstract void loadDefaultTool();
public abstract boolean execute(ThrowableRunnable<Exception> operation);
public abstract void execute(List<EditOperation> operations);
}
@@ -17,6 +17,7 @@ package com.intellij.designer.model;
import com.intellij.designer.palette.Item;
import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -92,7 +93,8 @@ public class MetaModel {
return myPaletteItem;
}
public void setPaletteItem(Item paletteItem) {
public void setPaletteItem(@NotNull Item paletteItem) {
myPaletteItem = paletteItem;
myPaletteItem.setMetaModel(this);
}
}
@@ -19,12 +19,15 @@ import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.designSurface.tools.DragTracker;
import com.intellij.designer.designSurface.tools.InputTool;
import com.intellij.designer.propertyTable.Property;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.util.containers.hash.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -38,6 +41,12 @@ public abstract class RadComponent {
private RadLayout myLayout;
private final Map<Object, Object> myClientProperties = new HashMap<Object, Object>();
//////////////////////////////////////////////////////////////////////////////////////////
//
// MetaModel
//
//////////////////////////////////////////////////////////////////////////////////////////
public MetaModel getMetaModel() {
return myMetaModel;
}
@@ -97,6 +106,8 @@ public abstract class RadComponent {
public void processDropOperation(OperationContext context) {
}
public void addSelectionActions(DefaultActionGroup actionGroup, JComponent shortcuts, List<RadComponent> selection) {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// layout
@@ -157,4 +168,49 @@ public abstract class RadComponent {
visitor.endVisit(this);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Operations
//
//////////////////////////////////////////////////////////////////////////////////////////
public boolean canDelete() {
return true;
}
public void delete() throws Exception {
}
public void copyTo(Element parentElement) throws Exception {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Utils
//
//////////////////////////////////////////////////////////////////////////////////////////
public static boolean isParentsContainedIn(List<RadComponent> components, RadComponent component) {
RadComponent parent = component.getParent();
while (parent != null) {
if (components.contains(parent)) {
return true;
}
parent = parent.getParent();
}
return false;
}
public static List<RadComponent> getPureSelection(List<RadComponent> selection) {
List<RadComponent> components = new ArrayList<RadComponent>();
for (RadComponent component : selection) {
if (!isParentsContainedIn(selection, component)) {
components.add(component);
}
}
return components;
}
}
@@ -18,16 +18,23 @@ package com.intellij.designer.model;
import com.intellij.designer.designSurface.ComponentDecorator;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class RadLayout {
public abstract ComponentDecorator getChildSelectionDecorator(RadComponent component);
public abstract ComponentDecorator getChildSelectionDecorator(RadComponent component, List<RadComponent> selection);
@Nullable
public EditOperation processChildOperation(OperationContext context) {
return null;
}
public void addSelectionActions(DefaultActionGroup actionGroup, JComponent shortcuts, List<RadComponent> selection) {
}
}
@@ -59,12 +59,12 @@ public final class Group implements PaletteGroup {
@Override
public ActionGroup getPopupActionGroup() {
return (ActionGroup)ActionManager.getInstance().getAction("Designer.PaletteGroupPopupMenu");
return null; // TODO: Auto-generated method stub
}
@Override
public Object getData(Project project, String dataId) {
return null; // TODO: Auto-generated method stub
return null; // TODO: Auto-generated method stub
}
@Override
@@ -15,6 +15,7 @@
*/
package com.intellij.designer.palette;
import com.intellij.designer.model.MetaModel;
import com.intellij.ide.dnd.DnDDragStartBean;
import com.intellij.ide.palette.PaletteItem;
import com.intellij.openapi.actionSystem.ActionGroup;
@@ -35,6 +36,8 @@ public final class Item implements PaletteItem {
private Icon myIcon;
private String myTooltip;
private MetaModel myMetaModel;
public Item(String title, String iconPath, String tooltip) {
myTitle = title;
myIconPath = iconPath;
@@ -66,11 +69,19 @@ public final class Item implements PaletteItem {
@Override
public ActionGroup getPopupActionGroup() {
return (ActionGroup)ActionManager.getInstance().getAction("Designer.PaletteItemPopupMenu");
return null; // TODO: Auto-generated method stub
}
@Override
public Object getData(Project project, String dataId) {
return null; // TODO: Auto-generated method stub
return null; // TODO: Auto-generated method stub
}
public MetaModel getMetaModel() {
return myMetaModel;
}
public void setMetaModel(MetaModel metaModel) {
myMetaModel = metaModel;
}
}
@@ -1,2 +1,3 @@
designer.toolwindow.name=Designer
designer.toolwindow.title=Component Tree
designer.toolwindow.title=Component Tree
command.delete.selection=Delete Selection