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 021package org.granite.builder.ui; 022 023import java.util.Arrays; 024import java.util.Collections; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028import java.util.Set; 029import java.util.TreeSet; 030 031import org.eclipse.core.resources.IFolder; 032import org.eclipse.core.runtime.CoreException; 033import org.eclipse.core.runtime.IPath; 034import org.eclipse.core.runtime.Path; 035import org.eclipse.swt.SWT; 036import org.eclipse.swt.events.SelectionAdapter; 037import org.eclipse.swt.events.SelectionEvent; 038import org.eclipse.swt.graphics.Rectangle; 039import org.eclipse.swt.layout.FillLayout; 040import org.eclipse.swt.layout.GridData; 041import org.eclipse.swt.layout.GridLayout; 042import org.eclipse.swt.widgets.Button; 043import org.eclipse.swt.widgets.Composite; 044import org.eclipse.swt.widgets.Label; 045import org.eclipse.swt.widgets.Tree; 046import org.eclipse.swt.widgets.TreeItem; 047import org.granite.builder.GraniteBuilderContext; 048import org.granite.builder.properties.Gas3Source; 049import org.granite.builder.properties.GraniteProperties; 050import org.granite.builder.util.ProjectUtil; 051import org.granite.builder.util.SWTUtil; 052 053/** 054 * @author Franck WOLFF 055 */ 056public 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}