001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
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    }