blob: e14fc4c90ae494dca321df3851d431a28fd1618c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.cpplite.project;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.Icon;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.modules.cpplite.project.ui.customizer.CustomizerProviderImpl;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.netbeans.spi.project.ProjectFactory;
import org.netbeans.spi.project.ProjectFactory2;
import org.netbeans.spi.project.ProjectState;
import org.netbeans.spi.project.ui.PrivilegedTemplates;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
import org.netbeans.spi.project.ui.RecommendedTemplates;
import org.openide.filesystems.FileObject;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbPreferences;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author lahvac
*/
public class CPPLiteProject implements Project {
public static final String PROJECT_KEY = "org-netbeans-modules-cpplite-project-CPPLiteProject";
public static final String KEY_COMPILE_COMMANDS = "compile-commands";
public static final String KEY_COMPILE_COMMANDS_EXECUTABLE = "compile-commands-executable";
public static final String KEY_NEXT_MARK = "next-mark";
public static final String KEY_IS_PROJECT = "is-project";
public static Preferences getRootPreferences(FileObject root) {
return getRootPreferences(root, true);
}
private static Preferences getRootPreferences(FileObject root, boolean create) {
String encoded = root.toURI().toString().replace("/", ".");
Preferences projectsRoot = NbPreferences.forModule(CPPLiteProject.class).node("projects");
try {
for (String key : projectsRoot.keys()) {
if (encoded.equals(projectsRoot.get(key, null))) {
return projectsRoot.node(key);
}
}
} catch (BackingStoreException ex) {
}
if (!create) {
return null;
}
synchronized (CPPLiteProject.class) {
int mark = projectsRoot.getInt(KEY_NEXT_MARK, 0);
String key = Integer.toHexString(mark);
projectsRoot.putInt(KEY_NEXT_MARK, mark + 1);
projectsRoot.put(key, encoded);
return projectsRoot.node(key);
}
}
public static Preferences getBuildPreferences(FileObject root) {
return getRootPreferences(root).node("build");
}
private final FileObject projectDirectory;
private final Lookup lookup;
private final AtomicReference<BuildConfiguration> buildConfigurations = new AtomicReference<>();
private CPPLiteProject(FileObject projectDirectory) {
this.projectDirectory = projectDirectory;
this.lookup = Lookups.fixed(new LogicalViewProviderImpl(this),
new ActionProviderImpl(this),
new CustomizerProviderImpl(this),
new CPPLiteCProjectConfigurationProvider(getRootPreferences(projectDirectory)),
new RecommendedTemplatesImpl(),
new PrivilegedTemplatesImpl(),
new ProjectInfo(this),
new ProjectOpenHookImpl(this),
this);
buildConfigurations.set(BuildConfiguration.read(getBuildPreferences(projectDirectory)));
}
@Override
public FileObject getProjectDirectory() {
return projectDirectory;
}
@Override
public Lookup getLookup() {
return lookup;
}
public BuildConfiguration getActiveBuildConfiguration() {
return buildConfigurations.get();
}
public void setActiveBuildConfiguration(BuildConfiguration config) {
buildConfigurations.set(config);
}
public String getCompileCommands() {
return getRootPreferences(projectDirectory).get(KEY_COMPILE_COMMANDS, "");
}
public void setCompileCommands(String compileCommands) {
getRootPreferences(projectDirectory).put(KEY_COMPILE_COMMANDS, compileCommands);
}
public String getCompileCommandsExecutable() {
return getRootPreferences(projectDirectory).get(KEY_COMPILE_COMMANDS_EXECUTABLE, "");
}
public void setCompileCommandsExecutable(String compileCommandsExecutable) {
getRootPreferences(projectDirectory).put(KEY_COMPILE_COMMANDS_EXECUTABLE, compileCommandsExecutable);
}
private static Icon loadProjectIcon() {
return ImageUtilities.image2Icon(ImageUtilities.loadImage("org/netbeans/modules/cpplite/project/resources/project.gif"));
}
@ServiceProvider(service=ProjectFactory.class)
public static final class FactoryImpl implements ProjectFactory2 {
@Override
public ProjectManager.Result isProject2(FileObject projectDirectory) {
Preferences prefs = getRootPreferences(projectDirectory, false);
if (prefs != null && prefs.getBoolean(KEY_IS_PROJECT, false)) {
return new ProjectManager.Result(loadProjectIcon());
}
return null;
}
@Override
public boolean isProject(FileObject projectDirectory) {
return isProject2(projectDirectory) != null;
}
@Override
public Project loadProject(FileObject projectDirectory, ProjectState state) throws IOException {
if (isProject(projectDirectory)) {
return new CPPLiteProject(projectDirectory);
}
return null;
}
@Override
public void saveProject(Project project) throws IOException, ClassCastException {
}
}
private static class RecommendedTemplatesImpl implements RecommendedTemplates {
private static final String[] TEMPLATES = new String[] {
"cpplite"
};
@Override
public String[] getRecommendedTypes() {
return TEMPLATES;
}
}
private static class PrivilegedTemplatesImpl implements PrivilegedTemplates {
private static final String[] TEMPLATES = new String[] {
"Templates/cpplite/CTemplate.c",
"Templates/cpplite/CPPTemplate.cpp",
"Templates/cpplite/HTemplate.h",
"Templates/cpplite/HPPTemplate.hpp",
};
@Override
public String[] getPrivilegedTemplates() {
return TEMPLATES;
}
}
private static final class ProjectInfo implements ProjectInformation {
private final Project prj;
public ProjectInfo(Project prj) {
this.prj = prj;
}
@Override
public String getName() {
return prj.getProjectDirectory().getNameExt();
}
@Override
public String getDisplayName() {
return prj.getProjectDirectory().getNameExt();
}
@Override
public Icon getIcon() {
return loadProjectIcon();
}
@Override
public Project getProject() {
return prj;
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {}
}
private static final class ProjectOpenHookImpl extends ProjectOpenedHook {
private final ClassPath source;
public ProjectOpenHookImpl(Project prj) {
this.source = ClassPathSupport.createClassPath(prj.getProjectDirectory());
}
@Override
protected void projectOpened() {
GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {source});
}
@Override
protected void projectClosed() {
GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, new ClassPath[] {source});
}
}
}