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.Collections;
025 import java.util.HashMap;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.Set;
029 import java.util.TreeSet;
030
031 import org.eclipse.core.resources.IFolder;
032 import org.eclipse.core.runtime.CoreException;
033 import org.eclipse.core.runtime.IPath;
034 import org.eclipse.core.runtime.Path;
035 import org.eclipse.swt.SWT;
036 import org.eclipse.swt.events.SelectionAdapter;
037 import org.eclipse.swt.events.SelectionEvent;
038 import org.eclipse.swt.graphics.Rectangle;
039 import org.eclipse.swt.layout.FillLayout;
040 import org.eclipse.swt.layout.GridData;
041 import org.eclipse.swt.layout.GridLayout;
042 import org.eclipse.swt.widgets.Button;
043 import org.eclipse.swt.widgets.Composite;
044 import org.eclipse.swt.widgets.Label;
045 import org.eclipse.swt.widgets.Tree;
046 import org.eclipse.swt.widgets.TreeItem;
047 import org.granite.builder.GraniteBuilderContext;
048 import org.granite.builder.properties.Gas3Source;
049 import org.granite.builder.properties.GraniteProperties;
050 import org.granite.builder.util.ProjectUtil;
051 import org.granite.builder.util.SWTUtil;
052
053 /**
054 * @author Franck WOLFF
055 */
056 public class SourcesPanel extends Composite {
057
058 private static final String INCLUDED = "Included: ";
059 private static final String EXCLUDED = "Excluded: ";
060 private static final String OUTPUT = "Output: ";
061 private static final String ALL = "(All)";
062 private static final String NONE = "(None)";
063
064 private final GraniteBuilderContext context;
065 private final GraniteProperties properties;
066
067 private Tree sourcesTree = null;
068 private boolean initialized = false;
069
070 public SourcesPanel(Composite parent, GraniteBuilderContext context) throws CoreException {
071 super(parent, SWT.NONE);
072 if (parent == null || context == null)
073 throw new NullPointerException("parent and context cannot be null");
074 this.context = context;
075 this.properties = context.getProperties();
076 initializeComponents();
077 }
078
079 public TreeSet<Gas3Source> getSources() {
080 if (!initialized)
081 return properties.getGas3().getSources();
082
083 TreeSet<Gas3Source> sources = new TreeSet<Gas3Source>();
084 for (TreeItem root : sourcesTree.getItems())
085 sources.add((Gas3Source)root.getData());
086 return sources;
087 }
088
089 @Override
090 public Rectangle getClientArea() {
091 initializeContent();
092 return super.getClientArea();
093 }
094
095 private void initializeContent() {
096 if (!initialized) {
097 for (Gas3Source source : properties.getGas3().getSources())
098 addSourceFolderTreeItem(source);
099 initialized = true;
100 }
101 }
102
103 private void initializeComponents() {
104 setLayout(new GridLayout(2, false));
105
106 Label text = new Label(this, SWT.NONE);
107 text.setText("Source folders used for generation:");
108 text.setLayoutData(SWTUtil.newGridData(SWT.NONE, 2));
109
110 sourcesTree = new Tree(this, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
111 sourcesTree.setLayoutData(new GridData(
112 GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL |
113 GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL
114 ));
115
116 Composite buttons = new Composite(this, SWT.NONE);
117 buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
118 buttons.setLayout(new FillLayout(SWT.VERTICAL));
119
120 final Button addButton = SWTUtil.newButton(buttons, "Add Folder...", true, new SelectionAdapter() {
121 @Override
122 public void widgetSelected(SelectionEvent e) {
123 addFoldersHandler(e);
124 }
125 });
126
127 final Button editButton = SWTUtil.newButton(buttons, "Edit...", false, new SelectionAdapter() {
128 @Override
129 public void widgetSelected(SelectionEvent e) {
130 editFolderAttributesHandler(e);
131 }
132 });
133
134 final Button removeButton = SWTUtil.newButton(buttons, "Remove", false, new SelectionAdapter() {
135 @Override
136 public void widgetSelected(SelectionEvent e) {
137 // Remove selected root items.
138 for (TreeItem item : sourcesTree.getSelection()) {
139 if (item.getParentItem() == null)
140 item.dispose();
141 }
142 // Disable remove button if there is no more root nodes.
143 if (sourcesTree.getItemCount() == 0)
144 ((Button)e.getSource()).setEnabled(false);
145 }
146 });
147
148 sourcesTree.addSelectionListener(new SelectionAdapter() {
149 @Override
150 public void widgetSelected(SelectionEvent e) {
151 // Enable/Disable buttons based on selected tree item.
152 boolean isRoot = (((TreeItem)e.item).getParentItem() == null);
153 removeButton.setEnabled(isRoot);
154 addButton.setEnabled(isRoot);
155 editButton.setEnabled(!isRoot);
156 }
157 });
158 }
159
160 private TreeItem addSourceFolderTreeItem(Gas3Source source) {
161 IFolder folder = context.getJavaProject().getProject().getFolder(source.getPath());
162
163 String displayedPath = folder.getFullPath().makeRelative().toString();
164 String icon = folder.exists() ? SWTUtil.IMG_PKG_FOLDER : SWTUtil.IMG_PKG_FOLDER_ERROR;
165
166 TreeItem root = SWTUtil.addTreeItem(sourcesTree, icon, displayedPath, null, null);
167 SWTUtil.addTreeItem(root, SWTUtil.IMG_INCLUDES, source.getIncludes(), INCLUDED, ALL);
168 SWTUtil.addTreeItem(root, SWTUtil.IMG_EXCLUDES, source.getExcludes(), EXCLUDED, NONE);
169 SWTUtil.addTreeItem(root, SWTUtil.IMG_OUT_FOLDER, source.getOutput(), OUTPUT, null);
170 root.setData(source);
171 return root;
172 }
173
174 private void addFoldersHandler(SelectionEvent event) {
175 // Get currently configured source folders.
176 TreeItem[] roots = sourcesTree.getItems();
177 IPath[] usedEntries = new IPath[roots.length];
178 for (int i = 0; i < usedEntries.length; i++)
179 usedEntries[i] = new Path(roots[i].getText());
180
181 // Run add folders dialog.
182 IPath[] selectedPaths = Dialogs.chooseSourceFolderEntries(
183 context.getJavaProject(),
184 getDisplay().getActiveShell(),
185 null,
186 usedEntries
187 );
188
189 // Rebuild sorted source folders list.
190 if (selectedPaths != null && selectedPaths.length > 0) {
191 selectedPaths = ProjectUtil.makeRelative(selectedPaths);
192 IPath projectPath = context.getJavaProject().getPath().makeRelative();
193
194 Set<IPath> newSourceFolders = new TreeSet<IPath>(ProjectUtil.IPATH_COMPARATOR);
195 newSourceFolders.addAll(Arrays.asList(usedEntries));
196 List<IPath> jSourceFolders = ProjectUtil.makeRelative(getSourceFolders());
197 for (IPath selectedPath : selectedPaths) {
198 if (selectedPath.equals(projectPath)) {
199 newSourceFolders.addAll(jSourceFolders);
200 break;
201 }
202 for (IPath jSourceFolder : jSourceFolders) {
203 if (jSourceFolder.matchingFirstSegments(selectedPath) >= 2)
204 newSourceFolders.add(jSourceFolder);
205 }
206 }
207
208 Map<IPath, TreeItem> rootMap = new HashMap<IPath, TreeItem>(roots.length);
209 for (TreeItem root : roots)
210 rootMap.put(new Path(root.getText()), root);
211
212 String defaultOutput = "as3";
213 for (IPath newSourceFolder : newSourceFolders) {
214 TreeItem root = rootMap.get(newSourceFolder);
215 if (root != null)
216 addSourceFolderTreeItem((Gas3Source)root.getData());
217 else {
218 String path = newSourceFolder.removeFirstSegments(1).makeRelative().toString();
219 TreeItem item = addSourceFolderTreeItem(new Gas3Source(path, null, null, defaultOutput));
220 item.setExpanded(true);
221 }
222 }
223
224 for (TreeItem root : roots)
225 root.dispose();
226 }
227 }
228
229 private void editFolderAttributesHandler(SelectionEvent event) {
230 TreeItem[] selection = sourcesTree.getSelection();
231 if (selection.length == 1 && selection[0].getParentItem() != null && selection[0].getParentItem().getParentItem() == null) {
232 Gas3Source source = (Gas3Source)selection[0].getParentItem().getData();
233 source = Dialogs.editSourceFolderAttributes(context.getJavaProject(), getDisplay().getActiveShell(), source);
234 SWTUtil.setTreeItemText(selection[0].getParentItem().getItem(0), source.getIncludes());
235 SWTUtil.setTreeItemText(selection[0].getParentItem().getItem(1), source.getExcludes());
236 SWTUtil.setTreeItemText(selection[0].getParentItem().getItem(2), source.getOutput());
237 selection[0].getParentItem().setData(source);
238 }
239 }
240
241 private List<IPath> getSourceFolders() {
242 try {
243 return ProjectUtil.getSourceFolders(context.getJavaProject());
244 } catch (CoreException e) {
245 return Collections.emptyList();
246 }
247 }
248 }