update copyright
[fedora-idea.git] / plugins / ui-designer / src / com / intellij / uiDesigner / componentTree / ComponentTreeBuilder.java
blobcdf2bde56c5a6112f90497726a1d5acfc7568123
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.uiDesigner.componentTree;
18 import com.intellij.ide.util.treeView.AbstractTreeBuilder;
19 import com.intellij.ide.util.treeView.NodeDescriptor;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.progress.ProgressIndicator;
22 import com.intellij.openapi.progress.util.StatusBarProgress;
23 import com.intellij.openapi.util.Comparing;
24 import com.intellij.uiDesigner.FormEditingUtil;
25 import com.intellij.uiDesigner.HierarchyChangeListener;
26 import com.intellij.uiDesigner.SelectionWatcher;
27 import com.intellij.uiDesigner.designSurface.GuiEditor;
28 import com.intellij.uiDesigner.propertyInspector.PropertyInspector;
29 import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager;
30 import com.intellij.uiDesigner.radComponents.RadComponent;
31 import com.intellij.uiDesigner.radComponents.RadContainer;
32 import org.jetbrains.annotations.NotNull;
34 import javax.swing.event.TreeSelectionEvent;
35 import javax.swing.event.TreeSelectionListener;
36 import javax.swing.tree.DefaultTreeModel;
37 import java.util.ArrayList;
38 import java.util.Comparator;
39 import java.util.Set;
41 /**
42 * @author Anton Katilin
43 * @author Vladimir Kondratyev
45 public final class ComponentTreeBuilder extends AbstractTreeBuilder {
46 private static final Logger LOG = Logger.getInstance("#com.intellij.componentTree.ComponentTreeBuilder");
48 private final GuiEditor myEditor;
49 private final MySelectionWatcher mySelectionWatcher;
50 /**
51 * More then 0 if we are inside some change. In this case we have not
52 * react on our own events.
54 private int myInsideChange;
55 private final MyHierarchyChangeListener myHierarchyChangeListener;
56 private MyTreeSelectionListener myTreeSelectionListener;
58 public ComponentTreeBuilder(final ComponentTree tree, @NotNull final GuiEditor editor) {
59 super(tree,(DefaultTreeModel)tree.getModel(), new ComponentTreeStructure(editor), MyComparator.ourComparator);
61 myEditor = editor;
62 mySelectionWatcher = new MySelectionWatcher(editor);
64 initRootNode();
65 syncSelection();
67 myTreeSelectionListener = new MyTreeSelectionListener();
68 myHierarchyChangeListener = new MyHierarchyChangeListener();
69 getTree().getSelectionModel().addTreeSelectionListener(myTreeSelectionListener);
70 editor.addHierarchyChangeListener(myHierarchyChangeListener);
74 public void dispose() {
75 myEditor.removeHierarchyChangeListener(myHierarchyChangeListener);
76 if (myTreeSelectionListener != null) {
77 getTree().getSelectionModel().removeTreeSelectionListener(myTreeSelectionListener);
78 myTreeSelectionListener = null;
80 mySelectionWatcher.dispose();
81 super.dispose();
84 private ComponentTreeStructure getComponentTreeStructure(){
85 return (ComponentTreeStructure)getTreeStructure();
88 protected boolean isAlwaysShowPlus(final NodeDescriptor descriptor){
89 return false;
92 protected boolean isAutoExpandNode(final NodeDescriptor descriptor){
93 return getComponentTreeStructure().isAutoExpandNode(descriptor);
96 public void beginUpdateSelection() {
97 myInsideChange++;
100 public void endUpdateSelection() {
101 myInsideChange--;
102 updateSelection();
106 * This method synchronizes selection in the tree with the selected
107 * RadComponent in the component hierarchy
109 private void syncSelection() {
110 // Found selected components
111 final RadContainer rootContainer=myEditor.getRootContainer();
112 final ArrayList<RadComponent> selection = new ArrayList<RadComponent>();
113 FormEditingUtil.iterate(
114 rootContainer,
115 new FormEditingUtil.ComponentVisitor<RadComponent>() {
116 public boolean visit(final RadComponent component) {
117 if(component.isSelected()){
118 selection.add(component);
120 return true;
124 if(selection.size() == 0){
125 // If there is no selected component in the hierarchy, then
126 // we have to select RadRootContainer
127 selection.add(rootContainer);
130 final ComponentPtr[] componentPtrs = new ComponentPtr[selection.size()];
131 for (int i = 0; i < selection.size(); i++) {
132 componentPtrs [i] = new ComponentPtr(myEditor, selection.get(i));
135 // Set selection in the tree
136 select(componentPtrs, null);
138 // Notify the ComponentTree that selected component changed
139 myEditor.fireSelectedComponentChanged();
142 @NotNull
143 protected ProgressIndicator createProgressIndicator() {
144 return new StatusBarProgress();
148 * Compares RadComponent based on their natural order in the container.
150 private static final class MyComparator implements Comparator<NodeDescriptor>{
151 public static final MyComparator ourComparator=new MyComparator();
153 private static int indexOf(final RadContainer container, final RadComponent component){
154 if (container != null) {
155 for(int i = container.getComponentCount() - 1; i >= 0 ; i--){
156 if(component.equals(container.getComponent(i))){
157 return i;
161 return -1;
164 public int compare(final NodeDescriptor descriptor1, final NodeDescriptor descriptor2) {
165 if (descriptor1 instanceof ComponentPtrDescriptor && descriptor2 instanceof ComponentPtrDescriptor) {
166 final RadComponent component1 = ((ComponentPtrDescriptor)descriptor1).getComponent();
167 final RadComponent component2 = ((ComponentPtrDescriptor)descriptor2).getComponent();
168 if (component1 == null || component2 == null) {
169 return 0;
171 final RadContainer container1 = component1.getParent();
172 final RadContainer container2 = component2.getParent();
173 if(Comparing.equal(container1, container2)){
174 return indexOf(container1, component1) - indexOf(container2, component2);
176 else{
177 return 0;
179 }else{
180 return 0;
186 * Synchronizes tree with GuiEditor
188 private final class MyHierarchyChangeListener implements HierarchyChangeListener{
189 public void hierarchyChanged(){
190 if(myInsideChange>0){
191 return;
194 myInsideChange++;
195 try{
196 updateFromRoot();
197 // After updating the tree we have to synchronize the selection in the tree
198 // with selected elemenet in the hierarchy
199 syncSelection();
200 }finally{
201 myInsideChange--;
207 * Synchronizes selection in the tree with selection in the editor
209 private final class MySelectionWatcher extends SelectionWatcher{
210 public MySelectionWatcher(final GuiEditor editor) {
211 super(editor);
214 protected void selectionChanged(final RadComponent component, final boolean ignored) {
215 updateSelection();
219 private void updateSelection() {
220 final PropertyInspector propertyInspector = UIDesignerToolWindowManager.getInstance(myEditor.getProject()).getPropertyInspector();
221 if (propertyInspector.isEditing()) {
222 propertyInspector.stopEditing();
225 if(myInsideChange > 0){
226 return;
228 myInsideChange++;
229 try {
230 updateFromRoot();
231 syncSelection();
232 } finally {
233 myInsideChange--;
238 * Synchronizes GuiEditor with the tree
240 private final class MyTreeSelectionListener implements TreeSelectionListener {
241 public void valueChanged(final TreeSelectionEvent e) {
242 if (myInsideChange>0) {
243 return;
246 final Set<ComponentPtr> selectedElements = getSelectedElements(ComponentPtr.class);
247 myInsideChange++;
248 try{
249 FormEditingUtil.clearSelection(myEditor.getRootContainer());
250 boolean hasComponentInTab = false;
251 int count = 0;
252 for(ComponentPtr ptr: selectedElements) {
253 if(ptr.isValid()) {
254 final RadComponent component=ptr.getComponent();
255 LOG.assertTrue(component!=null);
256 if (!hasComponentInTab) {
257 hasComponentInTab = FormEditingUtil.selectComponent(myEditor, component);
259 else {
260 component.setSelected(true);
262 if (++count == selectedElements.size()) {
263 myEditor.scrollComponentInView(component);
268 // Notify ComponentTree that selected component changed
269 myEditor.fireSelectedComponentChanged();
270 }finally{
271 myInsideChange--;