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.TreeSet;
025
026import org.eclipse.core.resources.IProject;
027import org.eclipse.core.runtime.CoreException;
028import org.eclipse.core.runtime.IPath;
029import org.eclipse.core.runtime.Path;
030import org.eclipse.swt.SWT;
031import org.eclipse.swt.events.SelectionAdapter;
032import org.eclipse.swt.events.SelectionEvent;
033import org.eclipse.swt.graphics.Rectangle;
034import org.eclipse.swt.layout.FillLayout;
035import org.eclipse.swt.layout.GridData;
036import org.eclipse.swt.layout.GridLayout;
037import org.eclipse.swt.widgets.Button;
038import org.eclipse.swt.widgets.Composite;
039import org.eclipse.swt.widgets.Label;
040import org.eclipse.swt.widgets.Tree;
041import org.eclipse.swt.widgets.TreeItem;
042import org.granite.builder.GraniteBuilderContext;
043import org.granite.builder.properties.Gas3Project;
044import org.granite.builder.properties.GraniteProperties;
045import org.granite.builder.util.ProjectUtil;
046import org.granite.builder.util.SWTUtil;
047
048/**
049 * @author Franck WOLFF
050 */
051public 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}