001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2007-2010 ADEQUATE SYSTEMS SARL
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.builder.ui;
022
023 import java.util.Arrays;
024 import java.util.TreeSet;
025
026 import org.eclipse.core.resources.IProject;
027 import org.eclipse.core.runtime.CoreException;
028 import org.eclipse.core.runtime.IPath;
029 import org.eclipse.core.runtime.Path;
030 import org.eclipse.swt.SWT;
031 import org.eclipse.swt.events.SelectionAdapter;
032 import org.eclipse.swt.events.SelectionEvent;
033 import org.eclipse.swt.graphics.Rectangle;
034 import org.eclipse.swt.layout.FillLayout;
035 import org.eclipse.swt.layout.GridData;
036 import org.eclipse.swt.layout.GridLayout;
037 import org.eclipse.swt.widgets.Button;
038 import org.eclipse.swt.widgets.Composite;
039 import org.eclipse.swt.widgets.Label;
040 import org.eclipse.swt.widgets.Tree;
041 import org.eclipse.swt.widgets.TreeItem;
042 import org.granite.builder.GraniteBuilderContext;
043 import org.granite.builder.properties.Gas3Project;
044 import org.granite.builder.properties.GraniteProperties;
045 import org.granite.builder.util.ProjectUtil;
046 import org.granite.builder.util.SWTUtil;
047
048 /**
049 * @author Franck WOLFF
050 */
051 public class ProjectsPanel extends Composite {
052
053 private final GraniteBuilderContext context;
054 private final GraniteProperties properties;
055
056 private Tree projectsTree = null;
057 private boolean initialized = false;
058
059 public ProjectsPanel(Composite parent, GraniteBuilderContext context) throws CoreException {
060 super(parent, SWT.NONE);
061 if (parent == null || context == null)
062 throw new NullPointerException("parent and context cannot be null");
063 this.context = context;
064 this.properties = context.getProperties();
065 initializeComponents();
066 }
067
068 public TreeSet<Gas3Project> getProjects() {
069 if (!initialized)
070 return properties.getGas3().getProjects();
071
072 TreeSet<Gas3Project> projects = new TreeSet<Gas3Project>();
073 for (TreeItem root : projectsTree.getItems())
074 projects.add((Gas3Project)root.getData());
075 return projects;
076 }
077
078 @Override
079 public Rectangle getClientArea() {
080 initializeContent();
081 return super.getClientArea();
082 }
083
084 private void initializeContent() {
085 if (!initialized) {
086 for (Gas3Project project : properties.getGas3().getProjects())
087 addProjectFolderTreeItem(project);
088 initialized = true;
089 }
090 }
091
092 private void initializeComponents() {
093 setLayout(new GridLayout(2, false));
094
095 Label text = new Label(this, SWT.NONE);
096 text.setText("Other granite projects used for generation:");
097 text.setLayoutData(SWTUtil.newGridData(SWT.NONE, 2));
098
099 projectsTree = new Tree(this, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
100 projectsTree.setLayoutData(new GridData(
101 GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL |
102 GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL
103 ));
104
105 Composite buttons = new Composite(this, SWT.NONE);
106 buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
107 buttons.setLayout(new FillLayout(SWT.VERTICAL));
108
109 final Button addButton = SWTUtil.newButton(buttons, "Add Project...", true, new SelectionAdapter() {
110 @Override
111 public void widgetSelected(SelectionEvent e) {
112 addProjectsHandler(e);
113 }
114 });
115
116 final Button removeButton = SWTUtil.newButton(buttons, "Remove", false, new SelectionAdapter() {
117 @Override
118 public void widgetSelected(SelectionEvent e) {
119 // Remove selected root items.
120 for (TreeItem item : projectsTree.getSelection()) {
121 if (item.getParentItem() == null)
122 item.dispose();
123 }
124 // Disable remove button if there is no more root nodes.
125 if (projectsTree.getItemCount() == 0)
126 ((Button)e.getSource()).setEnabled(false);
127 }
128 });
129
130 projectsTree.addSelectionListener(new SelectionAdapter() {
131 @Override
132 public void widgetSelected(SelectionEvent e) {
133 // Enable/Disable buttons based on selected tree item.
134 boolean isRoot = (((TreeItem)e.item).getParentItem() == null);
135 removeButton.setEnabled(isRoot);
136 addButton.setEnabled(isRoot);
137 }
138 });
139 }
140
141 private TreeItem addProjectFolderTreeItem(Gas3Project project) {
142 try {
143 IProject dependentProject = ProjectUtil.getProject(context.getJavaProject().getProject(), project.getPath());
144
145 String displayedPath = dependentProject.getFullPath().makeRelative().toString();
146 String icon = SWTUtil.IMG_GPROJECT_ERROR;
147 if (!dependentProject.exists())
148 displayedPath += " (does not exist)";
149 else if (!dependentProject.isOpen())
150 displayedPath += " (not opened)";
151 else if (!ProjectUtil.isGraniteProject(dependentProject))
152 displayedPath += " (not a granite project)";
153 else
154 icon = SWTUtil.IMG_GPROJECT;
155
156 TreeItem root = SWTUtil.addTreeItem(projectsTree, icon, displayedPath, null, null);
157 root.setData(project);
158
159 return root;
160 } catch (CoreException e) {
161 throw new RuntimeException(e);
162 }
163 }
164
165 private void addProjectsHandler(SelectionEvent event) {
166 // Get currently configured projects.
167 TreeItem[] roots = projectsTree.getItems();
168 IPath[] usedEntries = new IPath[roots.length];
169 for (int i = 0; i < usedEntries.length; i++)
170 usedEntries[i] = new Path(roots[i].getText());
171
172 // Run add projects dialog.
173 IPath[] selectedPaths = Dialogs.chooseProjectEntries(
174 context.getJavaProject(),
175 getDisplay().getActiveShell(),
176 null,
177 usedEntries
178 );
179
180 // Rebuild sorted projects list.
181 if (selectedPaths != null && selectedPaths.length > 0) {
182 selectedPaths = ProjectUtil.makeRelative(selectedPaths);
183
184 IPath[] entries = new IPath[usedEntries.length + selectedPaths.length];
185 System.arraycopy(usedEntries, 0, entries, 0, usedEntries.length);
186 System.arraycopy(selectedPaths, 0, entries, usedEntries.length, selectedPaths.length);
187 Arrays.sort(entries, ProjectUtil.IPATH_COMPARATOR);
188
189 for (TreeItem root : projectsTree.getItems())
190 root.dispose();
191
192 for (IPath path : entries)
193 addProjectFolderTreeItem(new Gas3Project(path.toString()));
194 }
195 }
196 }