From 8c46e308b3d8c80649ca61134c4ece5f429af43b Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 1 Jun 2012 20:41:08 +0400 Subject: [PATCH] Morphing --- .../designer/model/RadViewComponent.java | 16 ++++ .../designer/model/views-meta-model.xml | 2 + .../designer/actions/DesignerActionPanel.java | 17 +++- .../designer/actions/MorphingAction.java | 87 +++++++++++++++++++ .../componentTree/ComponentTreeBuilder.java | 8 +- .../componentTree/TreeEditableArea.java | 13 ++- .../designSurface/DesignerEditorPanel.java | 2 +- .../intellij/designer/model/MetaManager.java | 27 +++++- .../intellij/designer/model/MetaModel.java | 9 ++ .../intellij/designer/model/RadComponent.java | 3 + 10 files changed, 168 insertions(+), 16 deletions(-) create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/MorphingAction.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java index 1242352fdc87..5c6197721090 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java @@ -16,6 +16,7 @@ package com.intellij.android.designer.model; import com.android.ide.common.rendering.api.ViewInfo; +import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; import com.intellij.designer.model.RadVisualComponent; import com.intellij.designer.propertyTable.Property; @@ -250,4 +251,19 @@ public class RadViewComponent extends RadVisualComponent { child.copyTo(parent); } } + + @Override + public void morphingTo(final MetaModel target) throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + myTag.setName(target.getTag()); + } + }); + + setMetaModel(target); + + PropertyParser propertyParser = getRoot().getClientProperty(PropertyParser.KEY); + propertyParser.load(this); + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 5c36a1947d6a..1a2b8cf867fc 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -108,6 +108,8 @@ + + selection) { boolean update = isVisible(myDynamicGroup); - for (AnAction action : myDynamicGroup.getChildActionsOrStubs()) { - action.unregisterCustomShortcutSet(myShortcuts); + if (myDynamicGroup.getChildrenCount() > 0) { + for (AnAction action : myDynamicGroup.getChildActionsOrStubs()) { + action.unregisterCustomShortcutSet(myShortcuts); + } + myDynamicGroup.removeAll(); } - myDynamicGroup.removeAll(); for (RadComponent parent : RadComponent.getParents(selection)) { parent.getLayout().addSelectionActions(myDesigner, myDynamicGroup, myShortcuts, selection); @@ -162,7 +167,11 @@ public class DesignerActionPanel implements DataProvider { } } - public ActionGroup getPopupActions() { + public ActionGroup getPopupActions(EditableArea area) { + if (myDynamicPopupGroup.getChildrenCount() > 0) { + myDynamicPopupGroup.removeAll(); + } + MorphingAction.fill(myDesigner, myDynamicPopupGroup, area); return myPopupGroup; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/MorphingAction.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/MorphingAction.java new file mode 100644 index 000000000000..8f1563edf79c --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/MorphingAction.java @@ -0,0 +1,87 @@ +/* + * 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.DesignerEditorPanel; +import com.intellij.designer.designSurface.EditableArea; +import com.intellij.designer.model.MetaModel; +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.util.ThrowableRunnable; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class MorphingAction extends AnAction { + private final DesignerEditorPanel myDesigner; + private final List myComponents; + private final MetaModel myTarget; + + public MorphingAction(DesignerEditorPanel designer, List components, MetaModel target) { + super(target.getTag(), null, target.getIcon()); + myDesigner = designer; + myComponents = components; + myTarget = target; + } + + @Override + public void actionPerformed(AnActionEvent e) { + myDesigner.getToolProvider().execute(new ThrowableRunnable() { + @Override + public void run() throws Exception { + for (RadComponent component : myComponents) { + component.morphingTo(myTarget); + } + } + }, "Run Morphing action", true); + } + + public static void fill(DesignerEditorPanel designer, DefaultActionGroup group, EditableArea area) { + List selection = area.getSelection(); + if (selection.isEmpty()) { + return; + } + + MetaModel model = null; + for (RadComponent component : selection) { + if (model == null) { + model = component.getMetaModel(); + } + else if (model != component.getMetaModel()) { + return; + } + } + if (model == null) { + return; + } + + List models = model.getMorphingModels(); + if (models.isEmpty()) { + return; + } + + DefaultActionGroup morphingGroup = new DefaultActionGroup("Morphing", true); + for (MetaModel morphingModel : models) { + morphingGroup.add(new MorphingAction(designer, selection, morphingModel)); + } + + group.add(morphingGroup); + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java index 05da1098f8d4..e457b0a661c1 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java @@ -19,7 +19,6 @@ import com.intellij.designer.designSurface.ComponentSelectionListener; import com.intellij.designer.designSurface.DesignerEditorPanel; import com.intellij.designer.designSurface.EditableArea; import com.intellij.ide.util.treeView.AbstractTreeBuilder; -import com.intellij.openapi.actionSystem.ActionGroup; import javax.swing.tree.DefaultTreeModel; @@ -41,12 +40,7 @@ public final class ComponentTreeBuilder extends AbstractTreeBuilder implements C initRootNode(); mySurfaceArea = designer.getSurfaceArea(); - myTreeArea = new TreeEditableArea(tree, this) { - @Override - public ActionGroup getPopupActions() { - return mySurfaceArea.getPopupActions(); - } - }; + myTreeArea = new TreeEditableArea(tree, this, designer.getActionPanel()); myGlassLayer = new TreeGlassLayer(tree, designer.getToolProvider(), myTreeArea); myExpandStateHandler = new ExpandStateHandler(tree, designer, this); diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeEditableArea.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeEditableArea.java index 8a10fb1a0757..33335b817f39 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeEditableArea.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeEditableArea.java @@ -15,10 +15,12 @@ */ package com.intellij.designer.componentTree; +import com.intellij.designer.actions.DesignerActionPanel; import com.intellij.designer.designSurface.*; import com.intellij.designer.designSurface.tools.InputTool; import com.intellij.designer.model.RadComponent; import com.intellij.ide.util.treeView.AbstractTreeBuilder; +import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -37,14 +39,16 @@ import java.util.List; /** * @author Alexander Lobas */ -public abstract class TreeEditableArea implements EditableArea, FeedbackTreeLayer, TreeSelectionListener { +public final class TreeEditableArea implements EditableArea, FeedbackTreeLayer, TreeSelectionListener { private final EventListenerList myListenerList = new EventListenerList(); private final ComponentTree myTree; private final AbstractTreeBuilder myTreeBuilder; + private final DesignerActionPanel myActionPanel; - public TreeEditableArea(ComponentTree tree, AbstractTreeBuilder treeBuilder) { + public TreeEditableArea(ComponentTree tree, AbstractTreeBuilder treeBuilder, DesignerActionPanel actionPanel) { myTree = tree; myTreeBuilder = treeBuilder; + myActionPanel = actionPanel; hookSelection(); } @@ -225,6 +229,11 @@ public abstract class TreeEditableArea implements EditableArea, FeedbackTreeLaye return this; } + @Override + public ActionGroup getPopupActions() { + return myActionPanel.getPopupActions(this); + } + @Override public String getPopupPlace() { return ActionPlaces.GUI_DESIGNER_COMPONENT_TREE_POPUP; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index 93b235c2f877..0b498666fc4c 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -192,7 +192,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider @Override public ActionGroup getPopupActions() { - return myActionPanel.getPopupActions(); + return myActionPanel.getPopupActions(this); } @Override diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java index 4337bcf8161e..5a7666d275fc 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java @@ -64,13 +64,31 @@ public abstract class MetaManager { Element rootElement = document.getRootElement(); ClassLoader classLoader = getClass().getClassLoader(); + Map> modelToMorphing = new HashMap>(); + for (Object element : rootElement.getChildren(META)) { - loadModel(classLoader, (Element)element); + loadModel(classLoader, (Element)element, modelToMorphing); } for (Object element : rootElement.getChild(PALETTE).getChildren(GROUP)) { loadGroup(name, (Element)element); } + + for (Map.Entry> entry : modelToMorphing.entrySet()) { + MetaModel meta = entry.getKey(); + List morphingModels = new ArrayList(); + + for (String tag : entry.getValue()) { + MetaModel morphingModel = myTag2Model.get(tag); + if (morphingModel != null) { + morphingModels.add(morphingModel); + } + } + + if (!morphingModels.isEmpty()) { + meta.setMorphingModels(morphingModels); + } + } } catch (Throwable e) { LOG.error(e); @@ -78,7 +96,7 @@ public abstract class MetaManager { } @SuppressWarnings("unchecked") - private void loadModel(ClassLoader classLoader, Element element) throws Exception { + private void loadModel(ClassLoader classLoader, Element element, Map> modelToMorphing) throws Exception { String modelValue = element.getAttributeValue("model"); Class model = modelValue == null ? null : (Class)classLoader.loadClass(modelValue); String target = element.getAttributeValue("class"); @@ -145,6 +163,11 @@ public abstract class MetaManager { } } + Element morphing = element.getChild("morphing"); + if (morphing != null) { + modelToMorphing.put(meta, StringUtil.split(morphing.getAttribute("to").getValue(), " ")); + } + if (tag != null) { myTag2Model.put(tag, meta); } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java index ab019ead955c..81844aad55ef 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java @@ -45,6 +45,7 @@ public class MetaModel { private List myImportantProperties = Collections.emptyList(); private List myExpertProperties = Collections.emptyList(); private List myDeprecatedProperties = Collections.emptyList(); + private List myMorphingModels = Collections.emptyList(); public MetaModel(Class model, String target, String tag) { myModel = model; @@ -117,6 +118,14 @@ public class MetaModel { myPaletteItem.setMetaModel(this); } + public List getMorphingModels() { + return myMorphingModels; + } + + public void setMorphingModels(List morphingModels) { + myMorphingModels = morphingModels; + } + public List getInplaceProperties() { return myInplaceProperties; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java index ffd7f5ad3064..b935c5ffdc19 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java @@ -260,6 +260,9 @@ public abstract class RadComponent { public void copyTo(Element parentElement) throws Exception { } + public void morphingTo(MetaModel target) throws Exception { + } + ////////////////////////////////////////////////////////////////////////////////////////// // // Utils