1.1 --- a/python.core/release/platform_info.py Wed Feb 04 01:21:44 2015 -0800
1.2 +++ b/python.core/release/platform_info.py Tue Feb 24 01:58:36 2015 -0800
1.3 @@ -4,20 +4,25 @@
1.4 import os
1.5
1.6 command = sys.executable
1.7 -version = sys.version.split()[0]
1.8 +major = sys.version_info[0]
1.9 +minor = sys.version_info[1]
1.10 +micro = sys.version_info[2]
1.11 +sourceLevel = str(major) + '.' + str(minor)
1.12 +version = sourceLevel + '.' + str(micro)
1.13 isJava = sys.platform.count("java")
1.14 if isJava :
1.15 print("platform.name="+ "Jython " + version)
1.16 else:
1.17 print("platform.name="+ "Python " + version)
1.18 -if command != None :
1.19 +print("platform.sourcelevel=" + sourceLevel)
1.20 +if command != None :
1.21 print("python.command="+ command.replace("\\", "\\\\"))
1.22 path = ""
1.23 for pathItem in sys.path:
1.24 path += pathItem + os.pathsep
1.25 print("python.path="+path.replace("\\", "\\\\"))
1.26
1.27 -if isJava :
1.28 +if isJava :
1.29 from java.lang import System
1.30 classpath = System.getProperty('java.class.path')
1.31 print(classpath)
2.1 --- a/python.core/src/org/netbeans/modules/python/api/PythonExecution.java Wed Feb 04 01:21:44 2015 -0800
2.2 +++ b/python.core/src/org/netbeans/modules/python/api/PythonExecution.java Tue Feb 24 01:58:36 2015 -0800
2.3 @@ -28,7 +28,7 @@
2.4 * @author Allan Davis
2.5 * @author Jean-Yves
2.6 */
2.7 -public class PythonExecution {
2.8 +public final class PythonExecution {
2.9 // execution commands
2.10 private String command;
2.11 private String workingDirectory;
3.1 --- a/python.core/src/org/netbeans/modules/python/api/PythonPlatform.java Wed Feb 04 01:21:44 2015 -0800
3.2 +++ b/python.core/src/org/netbeans/modules/python/api/PythonPlatform.java Tue Feb 24 01:58:36 2015 -0800
3.3 @@ -32,6 +32,7 @@
3.4 private String interpreterConsoleComand;
3.5 private String interpreterArgs;
3.6 private String homeUrl;
3.7 + private String sourceLevel;
3.8 private boolean dirty;
3.9 // When adding properties, be sure to update the persistence code in PythonPlatformManager
3.10
3.11 @@ -72,6 +73,15 @@
3.12 this.interpreterConsoleComand = interpreterConsoleComand;
3.13 }
3.14
3.15 + public String getSourceLevel() {
3.16 + return sourceLevel;
3.17 + }
3.18 +
3.19 + public void setSourceLevel(String sourceLevel) {
3.20 + checkDirty(this.sourceLevel, sourceLevel);
3.21 + this.sourceLevel = sourceLevel;
3.22 + }
3.23 +
3.24 public List<String> getJavaPath() {
3.25 return javaPath;
3.26 }
4.1 --- a/python.core/src/org/netbeans/modules/python/api/PythonPlatformManager.java Wed Feb 04 01:21:44 2015 -0800
4.2 +++ b/python.core/src/org/netbeans/modules/python/api/PythonPlatformManager.java Tue Feb 24 01:58:36 2015 -0800
4.3 @@ -47,6 +47,7 @@
4.4 private static final String PLATFORM_INTEPRETER = ".interpreter"; // NOI18N
4.5 private static final String JAVA_LIB_DIR = "javalib"; // NOI18N
4.6 private static final String PLATFORM_NAME = "name"; // NOI18N
4.7 + private static final String SOURCE_LEVEL = "sourcelevel"; // NOI18N
4.8 private static final String INTERPRETER_ARGS = "args"; // NOI18N
4.9 private static final String CONSOLE_PATH = "console"; // NOI18N
4.10 private static final String PYTHON_LIB_DIR = "pythonlib"; // NOI18N
4.11 @@ -101,7 +102,7 @@
4.12 } catch (IOException ex) {
4.13 Exceptions.printStackTrace(ex);
4.14 }
4.15 -
4.16 +
4.17 return platform;
4.18 }
4.19
4.20 @@ -139,6 +140,7 @@
4.21 String libDir = p.get(PLATFORM_PREFIX + idDot + PYTHON_LIB_DIR);
4.22 String javaPath = p.get(PLATFORM_PREFIX + idDot + JAVA_LIB_DIR);
4.23 String name = p.get(PLATFORM_PREFIX + idDot + PLATFORM_NAME);
4.24 + String sourceLevel = p.get(PLATFORM_PREFIX + idDot + SOURCE_LEVEL);
4.25 String interpreterArgs = p.get(PLATFORM_PREFIX + idDot + INTERPRETER_ARGS);
4.26 String interpreterConsolePath = p.get(PLATFORM_PREFIX + idDot + CONSOLE_PATH);
4.27
4.28 @@ -155,6 +157,9 @@
4.29 if (name != null && name.length() > 0) {
4.30 platform.setName(name);
4.31 }
4.32 + if (sourceLevel != null && !sourceLevel.isEmpty()) {
4.33 + platform.setSourceLevel(sourceLevel);
4.34 + }
4.35 if (libDir != null && libDir.length() > 0) {
4.36 platform.setPythonPath(libDir.split(File.pathSeparator));
4.37 }
4.38 @@ -180,7 +185,7 @@
4.39 defaultPlatform = deflt.getId();
4.40 platforms.put(defaultPlatform, deflt);
4.41 }
4.42 -
4.43 +
4.44 if (Util.isFirstPlatformTouch()) {
4.45 RequestProcessor.getDefault().post(new Runnable() {
4.46 public void run() {
4.47 @@ -188,7 +193,7 @@
4.48 autoDetect();
4.49 }
4.50 }
4.51 - });
4.52 + });
4.53 }
4.54 }
4.55 }
4.56 @@ -216,7 +221,7 @@
4.57 EditableProperties props = PropertyUtils.getGlobalProperties();
4.58 clearProperties(platform, props);
4.59 putPlatformProperties(platform, props);
4.60 - PropertyUtils.putGlobalProperties(props);
4.61 + PropertyUtils.putGlobalProperties(props);
4.62 return null;
4.63 }
4.64 });
4.65 @@ -236,6 +241,7 @@
4.66 props.remove(PLATFORM_PREFIX + idDot + PYTHON_LIB_DIR);
4.67 props.remove(PLATFORM_PREFIX + idDot + JAVA_LIB_DIR);
4.68 props.remove(PLATFORM_PREFIX + idDot + PLATFORM_NAME);
4.69 + props.remove(PLATFORM_PREFIX + idDot + SOURCE_LEVEL);
4.70 props.remove(PLATFORM_PREFIX + idDot + INTERPRETER_ARGS);
4.71 props.remove(PLATFORM_PREFIX + idDot + CONSOLE_PATH);
4.72 }
4.73 @@ -264,6 +270,9 @@
4.74 if (platform.getName() != null) {
4.75 props.setProperty(PLATFORM_PREFIX + idDot + PLATFORM_NAME, platform.getName());
4.76 }
4.77 + if (platform.getSourceLevel() != null) {
4.78 + props.setProperty(PLATFORM_PREFIX + idDot + SOURCE_LEVEL, platform.getSourceLevel());
4.79 + }
4.80 if (platform.getInterpreterArgs() != null) {
4.81 props.setProperty(PLATFORM_PREFIX + idDot + INTERPRETER_ARGS, platform.getInterpreterArgs());
4.82 }
4.83 @@ -340,16 +349,21 @@
4.84
4.85 firePlatformsChanged();
4.86 }
4.87 -
4.88 +
4.89 public PythonPlatform findPlatformProperties(String cmd, String id) throws PythonException{
4.90 PythonPlatform platform = null;
4.91 try{
4.92 PythonExecution pye = new PythonExecution();
4.93 - pye.setCommand(cmd);
4.94 + int split = cmd.indexOf(" ");
4.95 + pye.setCommand(split > 0 ? cmd.substring(0, split) : cmd);
4.96 pye.setDisplayName("Python Properties");
4.97 File info = InstalledFileLocator.getDefault().locate(
4.98 "platform_info.py", "org.netbeans.modules.python.core", false);
4.99 pye.setScript(info.getAbsolutePath());
4.100 + if(split > 0) {
4.101 + String cmdArgs = cmd.substring(split).trim();
4.102 + pye.setCommandArgs(cmdArgs);
4.103 + }
4.104 pye.setShowControls(false);
4.105 pye.setShowInput(false);
4.106 pye.setShowWindow(false);
4.107 @@ -379,6 +393,7 @@
4.108 platform.setInterpreterConsoleComand(command);
4.109 // @@@Jean-Yves end of fix
4.110 platform.setName(name);
4.111 + platform.setSourceLevel(prop.getProperty("platform.sourcelevel"));
4.112 String pathString = prop.getProperty("python.path");
4.113 if(pathString != null)
4.114 platform.setPythonPath(pathString.split(File.pathSeparator));
4.115 @@ -490,7 +505,7 @@
4.116 }
4.117
4.118 }
4.119 -
4.120 +
4.121 private ArrayList<String> discoverJythonClasspath(String command){
4.122 ArrayList<String> temp = new ArrayList<String>();
4.123 //@@@jean-yves in some case bin is not there(jython 2.2.1 installer)
5.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/Debuggee.java Wed Feb 04 01:21:44 2015 -0800
5.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/Debuggee.java Tue Feb 24 01:58:36 2015 -0800
5.3 @@ -46,7 +46,6 @@
5.4 import org.netbeans.modules.python.api.PythonPlatform;
5.5 import org.netbeans.modules.python.debugger.actions.JpyDbgView;
5.6 import org.netbeans.modules.python.debugger.spi.PythonSession;
5.7 -import org.netbeans.modules.python.debugger.spi.PythonSourceDebuggee;
5.8 import org.openide.filesystems.FileObject;
5.9 import org.openide.filesystems.FileUtil;
5.10 import org.openide.loaders.DataObject;
6.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/DebuggerPythonLogger.java Wed Feb 04 01:21:44 2015 -0800
6.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/DebuggerPythonLogger.java Tue Feb 24 01:58:36 2015 -0800
6.3 @@ -62,7 +62,6 @@
6.4 import java.util.Set;
6.5 import org.netbeans.modules.python.debugger.spi.PythonEvent;
6.6 import org.netbeans.modules.python.debugger.spi.PythonSession;
6.7 -import org.netbeans.modules.python.debugger.spi.PythonSourceDebuggee;
6.8
6.9 /**
6.10 * Debugger's tasking entry point class
7.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/PythonDebugger.java Wed Feb 04 01:21:44 2015 -0800
7.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/PythonDebugger.java Tue Feb 24 01:58:36 2015 -0800
7.3 @@ -56,7 +56,6 @@
7.4 import org.netbeans.modules.python.debugger.backend.PluginEvent;
7.5 import org.netbeans.modules.python.debugger.spi.PythonEvent;
7.6 import org.netbeans.modules.python.debugger.spi.PythonSession;
7.7 -import org.netbeans.modules.python.debugger.spi.PythonSourceDebuggee;
7.8 import org.netbeans.modules.python.debugger.spi.SessionsModel;
7.9 import org.netbeans.modules.python.debugger.gui.PythonDebugContainer;
7.10 import org.netbeans.modules.python.debugger.gui.PythonVariableTreeDataNode;
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/PythonSourceDebuggee.java Tue Feb 24 01:58:36 2015 -0800
8.3 @@ -0,0 +1,81 @@
8.4 +/*
8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8.6 + *
8.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
8.8 + *
8.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
8.10 + * Other names may be trademarks of their respective owners.
8.11 + *
8.12 + * The contents of this file are subject to the terms of either the GNU
8.13 + * General Public License Version 2 only ("GPL") or the Common
8.14 + * Development and Distribution License("CDDL") (collectively, the
8.15 + * "License"). You may not use this file except in compliance with the
8.16 + * License. You can obtain a copy of the License at
8.17 + * http://www.netbeans.org/cddl-gplv2.html
8.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
8.19 + * specific language governing permissions and limitations under the
8.20 + * License. When distributing the software, include this License Header
8.21 + * Notice in each file and include the License file at
8.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
8.23 + * particular file as subject to the "Classpath" exception as provided
8.24 + * by Oracle in the GPL Version 2 section of the License file that
8.25 + * accompanied this code. If applicable, add the following below the
8.26 + * License Header, with the fields enclosed by brackets [] replaced by
8.27 + * your own identifying information:
8.28 + * "Portions Copyrighted [year] [name of copyright owner]"
8.29 + *
8.30 + * If you wish your version of this file to be governed by only the CDDL
8.31 + * or only the GPL Version 2, indicate your decision by adding
8.32 + * "[Contributor] elects to include this software in this distribution
8.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
8.34 + * single choice of license, a recipient has the option to distribute
8.35 + * your version of this file under either the CDDL, the GPL Version 2 or
8.36 + * to extend the choice of license to its licensees as provided above.
8.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
8.38 + * Version 2 license, then the option applies only if the new code is
8.39 + * made subject to such option by the copyright holder.
8.40 + *
8.41 + * Contributor(s):
8.42 + *
8.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
8.44 + */
8.45 +
8.46 +package org.netbeans.modules.python.debugger;
8.47 +
8.48 +import java.io.File ;
8.49 +import org.netbeans.modules.python.debugger.actions.JpyDbgView;
8.50 +import org.netbeans.modules.python.debugger.spi.PythonSession;
8.51 +import org.openide.filesystems.FileObject;
8.52 +
8.53 +/**
8.54 + * Node specialization for Python Sources debugging context
8.55 + * @author jean-yves Mengant
8.56 + */
8.57 +public interface PythonSourceDebuggee
8.58 +{
8.59 + /** Get the disk file for the python script.
8.60 + * @return the disk file, or null if none (but must be a file object)
8.61 + */
8.62 + File getFile ();
8.63 + /** Get the file object for the build script.
8.64 + * @return the file object, or null if none (but must be a disk file)
8.65 + */
8.66 + FileObject getFileObject ();
8.67 +
8.68 + /**
8.69 + bind a debug view object
8.70 + */
8.71 + public void setDebugView( JpyDbgView view ) ;
8.72 + public JpyDbgView getDebugView() ;
8.73 +
8.74 + /**
8.75 + execute current python shell action
8.76 + */
8.77 + //public void executePython()
8.78 + //throws PythonDebugException ;
8.79 +
8.80 + /** set current python session */
8.81 + public void setSession( PythonSession pythonSession ) ;
8.82 + public PythonSession getSession() ;
8.83 +
8.84 +}
9.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/actions/JpyDbgView.java Wed Feb 04 01:21:44 2015 -0800
9.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/actions/JpyDbgView.java Tue Feb 24 01:58:36 2015 -0800
9.3 @@ -47,7 +47,6 @@
9.4 import org.netbeans.modules.python.debugger.PythonDebugger;
9.5 import org.netbeans.modules.python.debugger.Utils;
9.6 import org.netbeans.modules.python.debugger.backend.PluginEvent;
9.7 -import org.netbeans.modules.python.debugger.backend.PluginEventListener;
9.8 import org.netbeans.modules.python.debugger.breakpoints.PythonBreakpoint;
9.9 import org.netbeans.modules.python.debugger.config.NetBeansFrontend;
9.10 import org.netbeans.modules.python.debugger.spi.PythonEvent;
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/actions/PluginEventListener.java Tue Feb 24 01:58:36 2015 -0800
10.3 @@ -0,0 +1,64 @@
10.4 +/*
10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10.6 + *
10.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
10.8 + *
10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
10.10 + * Other names may be trademarks of their respective owners.
10.11 + *
10.12 + * The contents of this file are subject to the terms of either the GNU
10.13 + * General Public License Version 2 only ("GPL") or the Common
10.14 + * Development and Distribution License("CDDL") (collectively, the
10.15 + * "License"). You may not use this file except in compliance with the
10.16 + * License. You can obtain a copy of the License at
10.17 + * http://www.netbeans.org/cddl-gplv2.html
10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
10.19 + * specific language governing permissions and limitations under the
10.20 + * License. When distributing the software, include this License Header
10.21 + * Notice in each file and include the License file at
10.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
10.23 + * particular file as subject to the "Classpath" exception as provided
10.24 + * by Oracle in the GPL Version 2 section of the License file that
10.25 + * accompanied this code. If applicable, add the following below the
10.26 + * License Header, with the fields enclosed by brackets [] replaced by
10.27 + * your own identifying information:
10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
10.29 + *
10.30 + * If you wish your version of this file to be governed by only the CDDL
10.31 + * or only the GPL Version 2, indicate your decision by adding
10.32 + * "[Contributor] elects to include this software in this distribution
10.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
10.34 + * single choice of license, a recipient has the option to distribute
10.35 + * your version of this file under either the CDDL, the GPL Version 2 or
10.36 + * to extend the choice of license to its licensees as provided above.
10.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
10.38 + * Version 2 license, then the option applies only if the new code is
10.39 + * made subject to such option by the copyright holder.
10.40 + *
10.41 + * Contributor(s):
10.42 + *
10.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
10.44 + */
10.45 +package org.netbeans.modules.python.debugger.actions;
10.46 +
10.47 +import org.netbeans.modules.python.debugger.backend.PluginEvent;
10.48 +import org.netbeans.modules.python.debugger.backend.PythonDebugException;
10.49 +
10.50 +/**
10.51 + *
10.52 + * used by pluggin implementors interfaces to get populated
10.53 + * With source debugging level instance
10.54 + *
10.55 + * @author jean-yves Mengant
10.56 + */
10.57 +public interface PluginEventListener {
10.58 +
10.59 + /**
10.60 + * populate debugging event to the UI plugin interface for
10.61 + * sources synchronization process
10.62 + * @param e
10.63 + * @throws PythonDebugException
10.64 + */
10.65 + public void newDebuggingEvent(PluginEvent e)
10.66 + throws PythonDebugException;
10.67 +}
11.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/backend/PluginEventListener.java Wed Feb 04 01:21:44 2015 -0800
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,61 +0,0 @@
11.4 -/*
11.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
11.6 - *
11.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
11.8 - *
11.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
11.10 - * Other names may be trademarks of their respective owners.
11.11 - *
11.12 - * The contents of this file are subject to the terms of either the GNU
11.13 - * General Public License Version 2 only ("GPL") or the Common
11.14 - * Development and Distribution License("CDDL") (collectively, the
11.15 - * "License"). You may not use this file except in compliance with the
11.16 - * License. You can obtain a copy of the License at
11.17 - * http://www.netbeans.org/cddl-gplv2.html
11.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
11.19 - * specific language governing permissions and limitations under the
11.20 - * License. When distributing the software, include this License Header
11.21 - * Notice in each file and include the License file at
11.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
11.23 - * particular file as subject to the "Classpath" exception as provided
11.24 - * by Oracle in the GPL Version 2 section of the License file that
11.25 - * accompanied this code. If applicable, add the following below the
11.26 - * License Header, with the fields enclosed by brackets [] replaced by
11.27 - * your own identifying information:
11.28 - * "Portions Copyrighted [year] [name of copyright owner]"
11.29 - *
11.30 - * If you wish your version of this file to be governed by only the CDDL
11.31 - * or only the GPL Version 2, indicate your decision by adding
11.32 - * "[Contributor] elects to include this software in this distribution
11.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
11.34 - * single choice of license, a recipient has the option to distribute
11.35 - * your version of this file under either the CDDL, the GPL Version 2 or
11.36 - * to extend the choice of license to its licensees as provided above.
11.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
11.38 - * Version 2 license, then the option applies only if the new code is
11.39 - * made subject to such option by the copyright holder.
11.40 - *
11.41 - * Contributor(s):
11.42 - *
11.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
11.44 - */
11.45 -package org.netbeans.modules.python.debugger.backend;
11.46 -
11.47 -/**
11.48 - *
11.49 - * used by pluggin implementors interfaces to get populated
11.50 - * With source debugging level instance
11.51 - *
11.52 - * @author jean-yves Mengant
11.53 - */
11.54 -public interface PluginEventListener {
11.55 -
11.56 - /**
11.57 - * populate debugging event to the UI plugin interface for
11.58 - * sources synchronization process
11.59 - * @param e
11.60 - * @throws PythonDebugException
11.61 - */
11.62 - public void newDebuggingEvent(PluginEvent e)
11.63 - throws PythonDebugException;
11.64 -}
12.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/gui/PythonDebugContainer.java Wed Feb 04 01:21:44 2015 -0800
12.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/gui/PythonDebugContainer.java Tue Feb 24 01:58:36 2015 -0800
12.3 @@ -71,7 +71,7 @@
12.4 import org.netbeans.modules.python.debugger.Utils;
12.5 import org.netbeans.modules.python.debugger.backend.DebuggerContextChangeListener;
12.6 import org.netbeans.modules.python.debugger.backend.PluginEvent;
12.7 -import org.netbeans.modules.python.debugger.backend.PluginEventListener;
12.8 +import org.netbeans.modules.python.debugger.actions.PluginEventListener;
12.9 import org.netbeans.modules.python.debugger.backend.PythonDebugClient;
12.10 import org.netbeans.modules.python.debugger.backend.PythonDebugEvent;
12.11 import org.netbeans.modules.python.debugger.backend.PythonDebugEventListener;
13.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/jpydaemon.py Wed Feb 04 01:21:44 2015 -0800
13.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/jpydaemon.py Tue Feb 24 01:58:36 2015 -0800
13.3 @@ -1483,9 +1483,8 @@
13.4 self.cmd = FREEZE
13.5 elif ( string.upper(verb) == "BP-"):
13.6 self.cmd = CLEAR_BP
13.7 - file , optarg = _utils.nextArg(arg)
13.8 - line , optarg = _utils.nextArg(optarg)
13.9 - self.clear_break( file, int(line) )
13.10 + arg , optarg = _utils.nextArg(arg) # split BP arguments
13.11 + self.clear_break( arg , int(optarg) )
13.12 self.cmd = FREEZE
13.13 elif ( string.upper(verb) == "KILL"):
13.14 self.cmd = QUIT
14.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/spi/PythonDebuggerTargetExecutor.java Wed Feb 04 01:21:44 2015 -0800
14.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/spi/PythonDebuggerTargetExecutor.java Tue Feb 24 01:58:36 2015 -0800
14.3 @@ -41,6 +41,7 @@
14.4 */
14.5 package org.netbeans.modules.python.debugger.spi;
14.6
14.7 +import org.netbeans.modules.python.debugger.PythonSourceDebuggee;
14.8 import org.openide.execution.ExecutorTask;
14.9 import java.io.IOException;
14.10 import java.io.OutputStream;
15.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/spi/PythonSourceDebuggee.java Wed Feb 04 01:21:44 2015 -0800
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,80 +0,0 @@
15.4 -/*
15.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
15.6 - *
15.7 - * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
15.8 - *
15.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
15.10 - * Other names may be trademarks of their respective owners.
15.11 - *
15.12 - * The contents of this file are subject to the terms of either the GNU
15.13 - * General Public License Version 2 only ("GPL") or the Common
15.14 - * Development and Distribution License("CDDL") (collectively, the
15.15 - * "License"). You may not use this file except in compliance with the
15.16 - * License. You can obtain a copy of the License at
15.17 - * http://www.netbeans.org/cddl-gplv2.html
15.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15.19 - * specific language governing permissions and limitations under the
15.20 - * License. When distributing the software, include this License Header
15.21 - * Notice in each file and include the License file at
15.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
15.23 - * particular file as subject to the "Classpath" exception as provided
15.24 - * by Oracle in the GPL Version 2 section of the License file that
15.25 - * accompanied this code. If applicable, add the following below the
15.26 - * License Header, with the fields enclosed by brackets [] replaced by
15.27 - * your own identifying information:
15.28 - * "Portions Copyrighted [year] [name of copyright owner]"
15.29 - *
15.30 - * If you wish your version of this file to be governed by only the CDDL
15.31 - * or only the GPL Version 2, indicate your decision by adding
15.32 - * "[Contributor] elects to include this software in this distribution
15.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
15.34 - * single choice of license, a recipient has the option to distribute
15.35 - * your version of this file under either the CDDL, the GPL Version 2 or
15.36 - * to extend the choice of license to its licensees as provided above.
15.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
15.38 - * Version 2 license, then the option applies only if the new code is
15.39 - * made subject to such option by the copyright holder.
15.40 - *
15.41 - * Contributor(s):
15.42 - *
15.43 - * Portions Copyrighted 2008 Sun Microsystems, Inc.
15.44 - */
15.45 -
15.46 -package org.netbeans.modules.python.debugger.spi;
15.47 -
15.48 -import java.io.File ;
15.49 -import org.netbeans.modules.python.debugger.actions.JpyDbgView;
15.50 -import org.openide.filesystems.FileObject;
15.51 -
15.52 -/**
15.53 - * Node specialization for Python Sources debugging context
15.54 - * @author jean-yves Mengant
15.55 - */
15.56 -public interface PythonSourceDebuggee
15.57 -{
15.58 - /** Get the disk file for the python script.
15.59 - * @return the disk file, or null if none (but must be a file object)
15.60 - */
15.61 - File getFile ();
15.62 - /** Get the file object for the build script.
15.63 - * @return the file object, or null if none (but must be a disk file)
15.64 - */
15.65 - FileObject getFileObject ();
15.66 -
15.67 - /**
15.68 - bind a debug view object
15.69 - */
15.70 - public void setDebugView( JpyDbgView view ) ;
15.71 - public JpyDbgView getDebugView() ;
15.72 -
15.73 - /**
15.74 - execute current python shell action
15.75 - */
15.76 - //public void executePython()
15.77 - //throws PythonDebugException ;
15.78 -
15.79 - /** set current python session */
15.80 - public void setSession( PythonSession pythonSession ) ;
15.81 - public PythonSession getSession() ;
15.82 -
15.83 -}
16.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/spi/TargetExecutor.java Wed Feb 04 01:21:44 2015 -0800
16.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/spi/TargetExecutor.java Tue Feb 24 01:58:36 2015 -0800
16.3 @@ -41,6 +41,7 @@
16.4 */
16.5 package org.netbeans.modules.python.debugger.spi;
16.6
16.7 +import org.netbeans.modules.python.debugger.PythonSourceDebuggee;
16.8 import org.openide.windows.InputOutput;
16.9 import org.openide.execution.ExecutorTask;
16.10 import org.openide.windows.IOProvider;
17.1 --- a/python.editor/manifest.mf Wed Feb 04 01:21:44 2015 -0800
17.2 +++ b/python.editor/manifest.mf Tue Feb 24 01:58:36 2015 -0800
17.3 @@ -3,4 +3,5 @@
17.4 OpenIDE-Module-Layer: org/netbeans/modules/python/editor/layer.xml
17.5 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/editor/Bundle.properties
17.6 AutoUpdate-Show-In-Client: false
17.7 +OpenIDE-Module-Specification-Version: 1.0
17.8
18.1 --- a/python.editor/nbproject/project.properties Wed Feb 04 01:21:44 2015 -0800
18.2 +++ b/python.editor/nbproject/project.properties Tue Feb 24 01:58:36 2015 -0800
18.3 @@ -15,7 +15,7 @@
18.4 auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaces-per-tab=4
18.5 auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.tab-size=4
18.6 auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.text-limit-width=100
18.7 -javac.source=1.6
18.8 +javac.source=1.7
18.9 javac.compilerargs=-Xlint -Xlint:-serial
18.10 nbm.needs.restart=true
18.11 spec.version.base=1.8.1
19.1 --- a/python.editor/nbproject/project.xml Wed Feb 04 01:21:44 2015 -0800
19.2 +++ b/python.editor/nbproject/project.xml Tue Feb 24 01:58:36 2015 -0800
19.3 @@ -15,6 +15,30 @@
19.4 </run-dependency>
19.5 </dependency>
19.6 <dependency>
19.7 + <code-name-base>org.eclipse.mylyn.wikitext.confluence.core</code-name-base>
19.8 + <build-prerequisite/>
19.9 + <compile-dependency/>
19.10 + <run-dependency>
19.11 + <specification-version>1.9.0</specification-version>
19.12 + </run-dependency>
19.13 + </dependency>
19.14 + <dependency>
19.15 + <code-name-base>org.eclipse.mylyn.wikitext.core</code-name-base>
19.16 + <build-prerequisite/>
19.17 + <compile-dependency/>
19.18 + <run-dependency>
19.19 + <specification-version>1.9.0</specification-version>
19.20 + </run-dependency>
19.21 + </dependency>
19.22 + <dependency>
19.23 + <code-name-base>org.eclipse.mylyn.wikitext.textile.core</code-name-base>
19.24 + <build-prerequisite/>
19.25 + <compile-dependency/>
19.26 + <run-dependency>
19.27 + <specification-version>1.9.0</specification-version>
19.28 + </run-dependency>
19.29 + </dependency>
19.30 + <dependency>
19.31 <code-name-base>org.netbeans.api.annotations.common</code-name-base>
19.32 <build-prerequisite/>
19.33 <compile-dependency/>
19.34 @@ -33,6 +57,15 @@
19.35 </run-dependency>
19.36 </dependency>
19.37 <dependency>
19.38 + <code-name-base>org.netbeans.api.progress</code-name-base>
19.39 + <build-prerequisite/>
19.40 + <compile-dependency/>
19.41 + <run-dependency>
19.42 + <release-version>1</release-version>
19.43 + <specification-version>1.38.1</specification-version>
19.44 + </run-dependency>
19.45 + </dependency>
19.46 + <dependency>
19.47 <code-name-base>org.netbeans.core.multiview</code-name-base>
19.48 <build-prerequisite/>
19.49 <compile-dependency/>
19.50 @@ -42,6 +75,15 @@
19.51 </run-dependency>
19.52 </dependency>
19.53 <dependency>
19.54 + <code-name-base>org.netbeans.libs.lucene</code-name-base>
19.55 + <build-prerequisite/>
19.56 + <compile-dependency/>
19.57 + <run-dependency>
19.58 + <release-version>3</release-version>
19.59 + <specification-version>3.16.1</specification-version>
19.60 + </run-dependency>
19.61 + </dependency>
19.62 + <dependency>
19.63 <code-name-base>org.netbeans.modules.csl.api</code-name-base>
19.64 <build-prerequisite/>
19.65 <compile-dependency/>
19.66 @@ -51,6 +93,15 @@
19.67 </run-dependency>
19.68 </dependency>
19.69 <dependency>
19.70 + <code-name-base>org.netbeans.modules.editor</code-name-base>
19.71 + <build-prerequisite/>
19.72 + <compile-dependency/>
19.73 + <run-dependency>
19.74 + <release-version>3</release-version>
19.75 + <specification-version>1.79.1.5.22.43</specification-version>
19.76 + </run-dependency>
19.77 + </dependency>
19.78 + <dependency>
19.79 <code-name-base>org.netbeans.modules.editor.bracesmatching</code-name-base>
19.80 <build-prerequisite/>
19.81 <compile-dependency/>
19.82 @@ -127,7 +178,15 @@
19.83 <compile-dependency/>
19.84 <run-dependency>
19.85 <release-version>1</release-version>
19.86 - <specification-version>1.21</specification-version>
19.87 + <specification-version>1.53.1</specification-version>
19.88 + </run-dependency>
19.89 + </dependency>
19.90 + <dependency>
19.91 + <code-name-base>org.netbeans.modules.editor.tools.storage</code-name-base>
19.92 + <build-prerequisite/>
19.93 + <compile-dependency/>
19.94 + <run-dependency>
19.95 + <specification-version>1.4.1</specification-version>
19.96 </run-dependency>
19.97 </dependency>
19.98 <dependency>
19.99 @@ -351,10 +410,11 @@
19.100 </module-dependencies>
19.101 <friend-packages>
19.102 <friend>org.netbeans.modules.python.project</friend>
19.103 + <friend>org.netbeans.modules.python.project2</friend>
19.104 <friend>org.netbeans.modules.python.testrunner</friend>
19.105 <package>org.netbeans.modules.python.editor</package>
19.106 + <package>org.netbeans.modules.python.editor.codecoverage</package>
19.107 <package>org.netbeans.modules.python.editor.lexer</package>
19.108 - <package>org.netbeans.modules.python.editor.codecoverage</package>
19.109 </friend-packages>
19.110 </data>
19.111 </configuration>
20.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonParser.java Wed Feb 04 01:21:44 2015 -0800
20.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonParser.java Tue Feb 24 01:58:36 2015 -0800
20.3 @@ -344,7 +344,7 @@
20.4 } catch (Throwable t) {
20.5 runtimeException = t;
20.6 StackTraceElement[] stackTrace = t.getStackTrace();
20.7 - if (stackTrace != null && stackTrace.length > 0 && stackTrace[0].getClassName().equals("org.python.antlr.runtime.tree.RewriteRuleElementStream")) {
20.8 + if (stackTrace != null && stackTrace.length > 0 && stackTrace[0].getClassName().startsWith("org.python.antlr")) {//.runtime.tree.RewriteRuleElementStream")) {
20.9 // This is issue 150921
20.10 // Don't bug user about it -- we already know
20.11 Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Encountered issue #150921", t);
21.1 --- a/python.editor/src/org/netbeans/modules/python/editor/file/PyDataObject.java Wed Feb 04 01:21:44 2015 -0800
21.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/file/PyDataObject.java Tue Feb 24 01:58:36 2015 -0800
21.3 @@ -51,6 +51,16 @@
21.4 ),
21.5 @ActionReference(
21.6 path = "Loaders/text/x-python/Actions",
21.7 + id = @ActionID(category = "Project", id = "org.netbeans.modules.project.ui.RunSingle"),
21.8 + position = 550
21.9 + ),
21.10 + @ActionReference(
21.11 + path = "Loaders/text/x.python/Actions",
21.12 + id = @ActionID(category = "Project", id = "org.netbeans.modules.project.ui.TestSingle"),
21.13 + position = 570
21.14 + ),
21.15 + @ActionReference(
21.16 + path = "Loaders/text/x-python/Actions",
21.17 id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"),
21.18 position = 600
21.19 ),
21.20 @@ -68,6 +78,17 @@
21.21 ),
21.22 @ActionReference(
21.23 path = "Loaders/text/x-python/Actions",
21.24 + id = @ActionID(category = "Refactoring", id = "org.netbeans.modules.refactoring.api.ui.WhereUsedAction"),
21.25 + position = 1050
21.26 + ),
21.27 + @ActionReference(
21.28 + path = "Loaders/text/x-python/Actions",
21.29 + id = @ActionID(category = "Refactoring", id = "RefactoringAll"),
21.30 + position = 1090,
21.31 + separatorAfter = 1095
21.32 + ),
21.33 + @ActionReference(
21.34 + path = "Loaders/text/x-python/Actions",
21.35 id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"),
21.36 position = 1100,
21.37 separatorAfter = 1200
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/file/PythonShebangSourceLevelQuery.java Tue Feb 24 01:58:36 2015 -0800
22.3 @@ -0,0 +1,125 @@
22.4 +/*
22.5 + * To change this license header, choose License Headers in Project Properties.
22.6 + * To change this template file, choose Tools | Templates
22.7 + * and open the template in the editor.
22.8 + */
22.9 +package org.netbeans.modules.python.editor.file;
22.10 +
22.11 +import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
22.12 +import java.io.FileNotFoundException;
22.13 +import java.io.IOException;
22.14 +import java.util.Scanner;
22.15 +import javax.swing.event.ChangeListener;
22.16 +import org.openide.filesystems.FileAttributeEvent;
22.17 +import org.openide.filesystems.FileChangeListener;
22.18 +import org.openide.filesystems.FileEvent;
22.19 +import org.openide.filesystems.FileObject;
22.20 +import org.openide.filesystems.FileRenameEvent;
22.21 +import org.openide.util.ChangeSupport;
22.22 +import org.openide.util.Exceptions;
22.23 +import org.openide.util.lookup.ServiceProvider;
22.24 +
22.25 +/**
22.26 + *
22.27 + * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
22.28 + */
22.29 +@ServiceProvider(service = SourceLevelQueryImplementation.class)
22.30 +public class PythonShebangSourceLevelQuery implements SourceLevelQueryImplementation {
22.31 +
22.32 + @Override
22.33 + public Result getSourceLevel(FileObject pythonFile) {
22.34 + if(!pythonFile.isFolder()) {
22.35 + return new ResultImpl(pythonFile);
22.36 + }
22.37 + return null;
22.38 + }
22.39 +
22.40 + private final static class ResultImpl implements Result, FileChangeListener {
22.41 + private final ChangeSupport cs = new ChangeSupport(this);
22.42 +
22.43 + private final FileObject pythonFile;
22.44 + private String sourceLevel = "";
22.45 +
22.46 + @SuppressWarnings("LeakingThisInConstructor")
22.47 + private ResultImpl(FileObject pythonFile) {
22.48 + this.pythonFile = pythonFile;
22.49 + this.pythonFile.addFileChangeListener(this);
22.50 + this.fileChanged(null);
22.51 + }
22.52 +
22.53 + @Override
22.54 + public void addChangeListener(ChangeListener listener) {
22.55 + this.cs.addChangeListener(listener);
22.56 + }
22.57 +
22.58 + @Override
22.59 + public void fileAttributeChanged(FileAttributeEvent fe) {
22.60 + }
22.61 +
22.62 + @Override
22.63 + public void fileChanged(FileEvent fe) {
22.64 + if (pythonFile.isValid()) {
22.65 + String shebang = null;
22.66 + try (Scanner sc = new Scanner(pythonFile.getInputStream())) {
22.67 + if (sc.hasNextLine()) {
22.68 + shebang = sc.nextLine();
22.69 + }
22.70 + } catch (FileNotFoundException ex) {
22.71 + Exceptions.printStackTrace(ex);
22.72 + }
22.73 + processShebang(shebang);
22.74 + }
22.75 + }
22.76 +
22.77 + @Override
22.78 + public void fileDataCreated(FileEvent fe) {
22.79 + }
22.80 +
22.81 + @Override
22.82 + public void fileDeleted(FileEvent fe) {
22.83 + }
22.84 +
22.85 + @Override
22.86 + public void fileFolderCreated(FileEvent fe) {
22.87 + }
22.88 +
22.89 + @Override
22.90 + public void fileRenamed(FileRenameEvent fe) {
22.91 + }
22.92 +
22.93 + @Override
22.94 + public String getSourceLevel() {
22.95 + return this.sourceLevel;
22.96 + }
22.97 +
22.98 + @Override
22.99 + public void removeChangeListener(ChangeListener listener) {
22.100 + this.cs.removeChangeListener(listener);
22.101 + }
22.102 +
22.103 + private void setSourceLevel(String sourceLevel) {
22.104 + this.sourceLevel = sourceLevel;
22.105 + cs.fireChange();
22.106 + }
22.107 +
22.108 + private void processShebang(String shebang) {
22.109 + if (shebang != null && shebang.startsWith("#!")) {
22.110 + try {
22.111 + Process proc = Runtime.getRuntime().exec(shebang.substring(2) + " --version");
22.112 + String version = null;
22.113 + try(Scanner sc = new Scanner(proc.getInputStream())) {
22.114 + if(sc.hasNextLine()) {
22.115 + version = sc.nextLine();
22.116 + }
22.117 + }
22.118 + proc.destroy();
22.119 + if(version != null && !version.isEmpty() && !version.equals(this.sourceLevel)) {
22.120 + setSourceLevel(version);
22.121 + }
22.122 + } catch(IOException ex) {
22.123 + Exceptions.printStackTrace(ex);
22.124 + }
22.125 + }
22.126 + }
22.127 + }
22.128 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/file/RunSingleCommand.java Tue Feb 24 01:58:36 2015 -0800
23.3 @@ -0,0 +1,117 @@
23.4 +package org.netbeans.modules.python.editor.file;
23.5 +
23.6 +import java.io.FileNotFoundException;
23.7 +import java.util.Scanner;
23.8 +import java.util.logging.Level;
23.9 +import java.util.logging.Logger;
23.10 +import javax.swing.JOptionPane;
23.11 +import org.netbeans.modules.python.api.PythonException;
23.12 +import org.netbeans.modules.python.api.PythonExecution;
23.13 +import org.netbeans.modules.python.api.PythonMIMEResolver;
23.14 +import org.netbeans.modules.python.api.PythonOptions;
23.15 +import org.netbeans.modules.python.api.PythonPlatform;
23.16 +import org.netbeans.modules.python.api.PythonPlatformManager;
23.17 +import org.netbeans.spi.project.ActionProvider;
23.18 +import org.openide.filesystems.FileObject;
23.19 +import org.openide.filesystems.FileUtil;
23.20 +import org.openide.loaders.DataObject;
23.21 +import org.openide.nodes.Node;
23.22 +import org.openide.util.Exceptions;
23.23 +import org.openide.util.Lookup;
23.24 +import org.openide.util.lookup.ServiceProvider;
23.25 +import org.openide.windows.TopComponent;
23.26 +
23.27 +/**
23.28 + *
23.29 + * @author Ralph Benjamin Ruijs
23.30 + */
23.31 +@ServiceProvider(service = ActionProvider.class)
23.32 +public class RunSingleCommand implements ActionProvider {
23.33 + private static final Logger LOG = Logger.getLogger(RunSingleCommand.class.getName());
23.34 +
23.35 + PythonPlatformManager manager = PythonPlatformManager.getInstance();
23.36 +
23.37 + public RunSingleCommand() {
23.38 + }
23.39 +
23.40 + private Node[] getSelectedNodes() {
23.41 + return TopComponent.getRegistry().getCurrentNodes();
23.42 + }
23.43 +
23.44 + @Override
23.45 + public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
23.46 + Node[] activatedNodes = getSelectedNodes();
23.47 + DataObject gdo = activatedNodes[0].getLookup().lookup(DataObject.class);
23.48 + FileObject file = gdo.getPrimaryFile();
23.49 + if (file.getMIMEType().equals(PythonMIMEResolver.PYTHON_MIME_TYPE)) {
23.50 + String path = FileUtil.toFile(file.getParent()).getAbsolutePath();
23.51 + String script = FileUtil.toFile(file).getAbsolutePath();
23.52 + String shebang = null;
23.53 + try(Scanner sc = new Scanner(file.getInputStream())) {
23.54 + if(sc.hasNextLine()) {
23.55 + shebang = sc.nextLine();
23.56 + }
23.57 + } catch (FileNotFoundException ex) {
23.58 + Exceptions.printStackTrace(ex);
23.59 + }
23.60 +
23.61 + PythonExecution pyexec = new PythonExecution();
23.62 + pyexec.setDisplayName(gdo.getName());
23.63 + pyexec.setWorkingDirectory(path);
23.64 + if (PythonOptions.getInstance().getPromptForArgs()) {
23.65 + String args = JOptionPane.showInputDialog("Enter the args for this script.", "");
23.66 + pyexec.setScriptArgs(args);
23.67 +
23.68 + }
23.69 + PythonPlatform platform = null;
23.70 + if (shebang != null && shebang.startsWith("#!")) {
23.71 + try {
23.72 + platform = manager.findPlatformProperties(shebang.substring(2), null);
23.73 + } catch (PythonException ex) {
23.74 + LOG.log(Level.WARNING, "Unable to get platform from shebang: " + shebang, ex);
23.75 + }
23.76 + }
23.77 + if(platform == null) {
23.78 + platform = manager.getPlatform(manager.getDefaultPlatform());
23.79 + if (platform == null) {
23.80 + return; // invalid platform user has been warn in check so safe to return
23.81 + }
23.82 + }
23.83 + pyexec.setCommand(platform.getInterpreterCommand());
23.84 + pyexec.setScript(script);
23.85 + pyexec.setCommandArgs(platform.getInterpreterArgs());
23.86 + pyexec.setPath(PythonPlatform.buildPath(platform.getPythonPath()));
23.87 +// pyexec.setJavaPath(PythonPlatform.buildPath(super.buildJavaPath(platform, pyProject)));
23.88 + pyexec.setShowControls(true);
23.89 + pyexec.setShowInput(true);
23.90 + pyexec.setShowWindow(true);
23.91 + pyexec.addStandardRecognizers();
23.92 +
23.93 +// PythonCoverageProvider coverageProvider = PythonCoverageProvider.get(pyProject);
23.94 +// if (coverageProvider != null && coverageProvider.isEnabled()) {
23.95 +// pyexec = coverageProvider.wrapWithCoverage(pyexec);
23.96 +// }
23.97 +
23.98 + pyexec.run();
23.99 + }
23.100 + }
23.101 +
23.102 + @Override
23.103 + public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
23.104 + boolean results = false; //super.enable(activatedNodes);
23.105 + Node[] activatedNodes = getSelectedNodes();
23.106 + if (activatedNodes != null && activatedNodes.length > 0) {
23.107 + DataObject gdo = activatedNodes[0].getLookup().lookup(DataObject.class);
23.108 + if (gdo != null && gdo.getPrimaryFile() != null) {
23.109 + results = gdo.getPrimaryFile().getMIMEType().equals(
23.110 + PythonMIMEResolver.PYTHON_MIME_TYPE);
23.111 + }
23.112 + }
23.113 + return results;
23.114 + }
23.115 +
23.116 + @Override
23.117 + public String[] getSupportedActions() {
23.118 + return new String[] {ActionProvider.COMMAND_RUN_SINGLE};
23.119 + }
23.120 +}
24.1 --- a/python.editor/src/org/netbeans/modules/python/editor/layer.xml Wed Feb 04 01:21:44 2015 -0800
24.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/layer.xml Tue Feb 24 01:58:36 2015 -0800
24.3 @@ -195,74 +195,6 @@
24.4 <folder name="x-python">
24.5 <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/netbeans/modules/python/editor/resources/pyNode25.png"/>
24.6 <attr name="iconBase" stringvalue="org/netbeans/modules/python/editor/resources/pyNode25.png"/>
24.7 - <folder name="Actions">
24.8 -
24.9 - <file name="RefactoringAll.shadow">
24.10 - <attr name="originalFile" stringvalue="Actions/Refactoring/RefactoringAll.instance"/>
24.11 - <attr name="position" intvalue="1800"/>
24.12 - </file>
24.13 - <file name="RefactoringWhereUsed.shadow">
24.14 - <attr name="originalFile" stringvalue="Actions/Refactoring/org-netbeans-modules-refactoring-api-ui-WhereUsedAction.instance"/>
24.15 - <attr name="position" intvalue="1700"/>
24.16 - </file>
24.17 - <file name="org-openide-actions-CopyAction.shadow">
24.18 - <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CopyAction.instance"/>
24.19 - <attr name="position" intvalue="500"/>
24.20 - </file>
24.21 - <file name="org-openide-actions-CutAction.shadow">
24.22 - <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CutAction.instance"/>
24.23 - <attr name="position" intvalue="400"/>
24.24 - </file>
24.25 - <file name="org-openide-actions-DeleteAction.shadow">
24.26 - <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-DeleteAction.instance"/>
24.27 - <attr name="position" intvalue="700"/>
24.28 - </file>
24.29 - <file name="org-openide-actions-FileSystemAction.shadow">
24.30 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-FileSystemAction.instance"/>
24.31 - <attr name="position" intvalue="200"/>
24.32 - </file>
24.33 - <file name="org-openide-actions-OpenAction.shadow">
24.34 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-OpenAction.instance"/>
24.35 - <attr name="position" intvalue="100"/>
24.36 - </file>
24.37 - <file name="org-openide-actions-PropertiesAction.shadow">
24.38 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-PropertiesAction.instance"/>
24.39 - <attr name="position" intvalue="1300"/>
24.40 - </file>
24.41 - <file name="org-openide-actions-RenameAction.shadow">
24.42 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-RenameAction.instance"/>
24.43 - <attr name="position" intvalue="800"/>
24.44 - </file>
24.45 - <file name="org-openide-actions-SaveAsTemplateAction.shadow">
24.46 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-SaveAsTemplateAction.instance"/>
24.47 - <attr name="position" intvalue="1000"/>
24.48 - </file>
24.49 - <file name="org-openide-actions-ToolsAction.shadow">
24.50 - <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-ToolsAction.instance"/>
24.51 - <attr name="position" intvalue="1200"/>
24.52 - </file>
24.53 - <file name="sep-1.instance">
24.54 - <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
24.55 - <attr name="position" intvalue="300"/>
24.56 - </file>
24.57 - <file name="sep-2.instance">
24.58 - <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
24.59 - <attr name="position" intvalue="600"/>
24.60 - </file>
24.61 - <file name="sep-3.instance">
24.62 - <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
24.63 - <attr name="position" intvalue="900"/>
24.64 - </file>
24.65 - <file name="sep-4.instance">
24.66 - <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
24.67 - <attr name="position" intvalue="1100"/>
24.68 - </file>
24.69 -
24.70 - <file name="RefactoringSeparator-1.instance">
24.71 - <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
24.72 - <attr name="position" intvalue="1900"/>
24.73 - </file>
24.74 - </folder>
24.75 </folder>
24.76 <folder name="x-python-compiled">
24.77 <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/netbeans/modules/python/editor/resources/pyc_16.png"/>
25.1 --- a/python.editor/src/org/netbeans/modules/python/editor/templates/executable_module.py.ftl Wed Feb 04 01:21:44 2015 -0800
25.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/templates/executable_module.py.ftl Tue Feb 24 01:58:36 2015 -0800
25.3 @@ -1,4 +1,8 @@
25.4 -#! /usr/bin/python
25.5 +<#if python3style?? && python3style>
25.6 +#!/usr/bin/env python3
25.7 +<#else>
25.8 +#!/usr/bin/env python2
25.9 +</#if>
25.10
25.11 <#-- This is a FreeMarker template -->
25.12 <#-- You can change the contents of the license inserted into
25.13 @@ -7,8 +11,9 @@
25.14 <#assign licensePrefix = "# ">
25.15 <#include "../Licenses/license-${project.license}.txt">
25.16
25.17 -__author__="${user}"
25.18 -__date__ ="$${date} ${time}$"
25.19 -
25.20 if __name__ == "__main__":
25.21 - print "Hello World";
25.22 +<#if python3style?? && python3style>
25.23 + print("Hello World")
25.24 +<#else>
25.25 + print "Hello World"
25.26 +</#if>
25.27 \ No newline at end of file
26.1 --- a/python.editor/src/org/netbeans/modules/python/editor/templates/init.py.ftl Wed Feb 04 01:21:44 2015 -0800
26.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/templates/init.py.ftl Tue Feb 24 01:58:36 2015 -0800
26.3 @@ -1,2 +0,0 @@
26.4 -__author__="${user}"
26.5 -__date__ ="$${date} ${time}$"
26.6 \ No newline at end of file
27.1 --- a/python.editor/src/org/netbeans/modules/python/editor/templates/module.py.ftl Wed Feb 04 01:21:44 2015 -0800
27.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/templates/module.py.ftl Tue Feb 24 01:58:36 2015 -0800
27.3 @@ -5,9 +5,6 @@
27.4 <#assign licensePrefix = "# ">
27.5 <#include "../Licenses/license-${project.license}.txt">
27.6
27.7 -__author__="${user}"
27.8 -__date__ ="$${date} ${time}$"
27.9 -
27.10 if __name__ == "__main__":
27.11 <#if python3style?? && python3style>
27.12 print("Hello World")
28.1 --- a/python.editor/src/org/netbeans/modules/python/editor/templates/setup.py.ftl Wed Feb 04 01:21:44 2015 -0800
28.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/templates/setup.py.ftl Tue Feb 24 01:58:36 2015 -0800
28.3 @@ -1,6 +1,3 @@
28.4 -__author__="${user}"
28.5 -__date__ ="$${date} ${time}$"
28.6 -
28.7 from setuptools import setup,find_packages
28.8
28.9 setup (
28.10 @@ -16,7 +13,7 @@
28.11 author = '${user}',
28.12 author_email = '',
28.13
28.14 - summary = 'Just another Python package for the cheese shop',
28.15 + #summary = 'Just another Python package for the cheese shop',
28.16 url = '',
28.17 license = '',
28.18 long_description= 'Long description of the package',
29.1 --- a/python.kit/nbproject/project.xml Wed Feb 04 01:21:44 2015 -0800
29.2 +++ b/python.kit/nbproject/project.xml Tue Feb 24 01:58:36 2015 -0800
29.3 @@ -46,7 +46,7 @@
29.4 <dependency>
29.5 <code-name-base>org.netbeans.modules.python.editor</code-name-base>
29.6 <run-dependency>
29.7 - <specification-version>1.6</specification-version>
29.8 + <specification-version>1.0</specification-version>
29.9 </run-dependency>
29.10 </dependency>
29.11 <dependency>
29.12 @@ -79,6 +79,12 @@
29.13 <specification-version>0.1</specification-version>
29.14 </run-dependency>
29.15 </dependency>
29.16 + <dependency>
29.17 + <code-name-base>org.netbeans.modules.python.project2</code-name-base>
29.18 + <run-dependency>
29.19 + <specification-version>1.0</specification-version>
29.20 + </run-dependency>
29.21 + </dependency>
29.22 </module-dependencies>
29.23 <public-packages/>
29.24 </data>
30.1 --- a/python.project/src/org/netbeans/modules/python/project/queries/PythonProjectSourceLevelQuery.java Wed Feb 04 01:21:44 2015 -0800
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,29 +0,0 @@
30.4 -/*
30.5 - * To change this license header, choose License Headers in Project Properties.
30.6 - * To change this template file, choose Tools | Templates
30.7 - * and open the template in the editor.
30.8 - */
30.9 -package org.netbeans.modules.python.project.queries;
30.10 -
30.11 -import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
30.12 -import org.netbeans.api.project.FileOwnerQuery;
30.13 -import org.netbeans.api.project.Project;
30.14 -import org.openide.filesystems.FileObject;
30.15 -import org.openide.util.lookup.ServiceProvider;
30.16 -
30.17 -@ServiceProvider(service = SourceLevelQueryImplementation.class)
30.18 -public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
30.19 -
30.20 - @Override
30.21 - public Result getSourceLevel(FileObject pythonFile) {
30.22 - final Project project = FileOwnerQuery.getOwner(pythonFile);
30.23 - if (project != null) {
30.24 - SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
30.25 - if (impl != null) {
30.26 - return impl.getSourceLevel(pythonFile);
30.27 - }
30.28 - }
30.29 - return null;
30.30 - }
30.31 -
30.32 -}
31.1 --- a/python.project/src/org/netbeans/modules/python/project/queries/PythonShebangSourceLevelQuery.java Wed Feb 04 01:21:44 2015 -0800
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,125 +0,0 @@
31.4 -/*
31.5 - * To change this license header, choose License Headers in Project Properties.
31.6 - * To change this template file, choose Tools | Templates
31.7 - * and open the template in the editor.
31.8 - */
31.9 -package org.netbeans.modules.python.project.queries;
31.10 -
31.11 -import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
31.12 -import java.io.FileNotFoundException;
31.13 -import java.io.IOException;
31.14 -import java.util.HashSet;
31.15 -import java.util.Scanner;
31.16 -import java.util.Set;
31.17 -import javax.swing.event.ChangeEvent;
31.18 -import javax.swing.event.ChangeListener;
31.19 -import org.openide.filesystems.FileAttributeEvent;
31.20 -import org.openide.filesystems.FileChangeListener;
31.21 -import org.openide.filesystems.FileEvent;
31.22 -import org.openide.filesystems.FileObject;
31.23 -import org.openide.filesystems.FileRenameEvent;
31.24 -import org.openide.util.ChangeSupport;
31.25 -import org.openide.util.Exceptions;
31.26 -import org.openide.util.lookup.ServiceProvider;
31.27 -
31.28 -/**
31.29 - *
31.30 - * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
31.31 - */
31.32 -@ServiceProvider(service = SourceLevelQueryImplementation.class)
31.33 -public class PythonShebangSourceLevelQuery implements SourceLevelQueryImplementation {
31.34 -
31.35 - @Override
31.36 - public Result getSourceLevel(FileObject pythonFile) {
31.37 - return new ResultImpl(pythonFile);
31.38 - }
31.39 -
31.40 - private final static class ResultImpl implements Result, FileChangeListener {
31.41 - private final ChangeSupport cs = new ChangeSupport(this);
31.42 -
31.43 - private final FileObject pythonFile;
31.44 - private String sourceLevel = "";
31.45 -
31.46 - @SuppressWarnings("LeakingThisInConstructor")
31.47 - private ResultImpl(FileObject pythonFile) {
31.48 - this.pythonFile = pythonFile;
31.49 - this.pythonFile.addFileChangeListener(this);
31.50 - this.fileChanged(null);
31.51 - }
31.52 -
31.53 - @Override
31.54 - public void addChangeListener(ChangeListener listener) {
31.55 - this.cs.addChangeListener(listener);
31.56 - }
31.57 -
31.58 - @Override
31.59 - public void fileAttributeChanged(FileAttributeEvent fe) {
31.60 - }
31.61 -
31.62 - @Override
31.63 - public void fileChanged(FileEvent fe) {
31.64 - if (pythonFile.isValid()) {
31.65 - String shebang = null;
31.66 - try (Scanner sc = new Scanner(pythonFile.getInputStream())) {
31.67 - if (sc.hasNextLine()) {
31.68 - shebang = sc.nextLine();
31.69 - }
31.70 - } catch (FileNotFoundException ex) {
31.71 - Exceptions.printStackTrace(ex);
31.72 - }
31.73 - processShebang(shebang);
31.74 - }
31.75 - }
31.76 -
31.77 - @Override
31.78 - public void fileDataCreated(FileEvent fe) {
31.79 - }
31.80 -
31.81 - @Override
31.82 - public void fileDeleted(FileEvent fe) {
31.83 - }
31.84 -
31.85 - @Override
31.86 - public void fileFolderCreated(FileEvent fe) {
31.87 - }
31.88 -
31.89 - @Override
31.90 - public void fileRenamed(FileRenameEvent fe) {
31.91 - }
31.92 -
31.93 - @Override
31.94 - public String getSourceLevel() {
31.95 - return this.sourceLevel;
31.96 - }
31.97 -
31.98 - @Override
31.99 - public void removeChangeListener(ChangeListener listener) {
31.100 - this.cs.removeChangeListener(listener);
31.101 - }
31.102 -
31.103 - private void setSourceLevel(String sourceLevel) {
31.104 - this.sourceLevel = sourceLevel;
31.105 - cs.fireChange();
31.106 - }
31.107 -
31.108 - private void processShebang(String shebang) {
31.109 - if (shebang != null && shebang.startsWith("#!")) {
31.110 - try {
31.111 - Process proc = Runtime.getRuntime().exec(shebang.substring(2) + " --version");
31.112 - String version = null;
31.113 - try(Scanner sc = new Scanner(proc.getInputStream())) {
31.114 - if(sc.hasNextLine()) {
31.115 - version = sc.nextLine();
31.116 - }
31.117 - }
31.118 - proc.destroy();
31.119 - if(version != null && !version.isEmpty() && !version.equals(this.sourceLevel)) {
31.120 - setSourceLevel(version);
31.121 - }
31.122 - } catch(IOException ex) {
31.123 - Exceptions.printStackTrace(ex);
31.124 - }
31.125 - }
31.126 - }
31.127 - }
31.128 -}
32.1 --- a/python.project/src/org/netbeans/modules/python/project/templates/EmptyPythonProjectDescription.html Wed Feb 04 01:21:44 2015 -0800
32.2 +++ b/python.project/src/org/netbeans/modules/python/project/templates/EmptyPythonProjectDescription.html Tue Feb 24 01:58:36 2015 -0800
32.3 @@ -7,6 +7,6 @@
32.4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
32.5 </head>
32.6 <body>
32.7 - New Empty Python Project
32.8 + New Empty Python Project using Ant
32.9 </body>
32.10 </html>
33.1 --- a/python.project/src/org/netbeans/modules/python/project/templates/ExistingPythonProjectDescription.html Wed Feb 04 01:21:44 2015 -0800
33.2 +++ b/python.project/src/org/netbeans/modules/python/project/templates/ExistingPythonProjectDescription.html Tue Feb 24 01:58:36 2015 -0800
33.3 @@ -9,6 +9,6 @@
33.4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
33.5 </head>
33.6 <body>
33.7 - New Python Project with Existing Sources
33.8 + New Python Project with Existing Sources using Ant
33.9 </body>
33.10 </html>
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/python.project2/build.xml Tue Feb 24 01:58:36 2015 -0800
34.3 @@ -0,0 +1,8 @@
34.4 +<?xml version="1.0" encoding="UTF-8"?>
34.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
34.6 +<!-- for some information on what you could do (e.g. targets to override). -->
34.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
34.8 +<project name="contrib/python.project" default="netbeans" basedir=".">
34.9 + <description>Builds, tests, and runs the project org.netbeans.modules.python.project.</description>
34.10 + <import file="../../nbbuild/templates/projectized.xml"/>
34.11 +</project>
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/python.project2/manifest.mf Tue Feb 24 01:58:36 2015 -0800
35.3 @@ -0,0 +1,7 @@
35.4 +Manifest-Version: 1.0
35.5 +AutoUpdate-Show-In-Client: true
35.6 +OpenIDE-Module: org.netbeans.modules.python.project2
35.7 +OpenIDE-Module-Layer: org/netbeans/modules/python/project2/layer.xml
35.8 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/python/project2/Bundle.properties
35.9 +OpenIDE-Module-Specification-Version: 1.0
35.10 +
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/python.project2/nbproject/project.properties Tue Feb 24 01:58:36 2015 -0800
36.3 @@ -0,0 +1,15 @@
36.4 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=true
36.5 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=4
36.6 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=4
36.7 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=4
36.8 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
36.9 +auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
36.10 +auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.alignMultilineArrayInit=true
36.11 +auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.blankLinesAfterClassHeader=0
36.12 +auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.indentCasesFromSwitch=false
36.13 +auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceAfterTypeCast=false
36.14 +javac.source=1.7
36.15 +javac.compilerargs=-Xlint -Xlint:-serial
36.16 +
36.17 +test-unit-sys-prop.xtest.python.home=${netbeans.dest.dir}/python/jython-2.5.1
36.18 +test-unit-sys-prop.xtest.platform_info.py=${netbeans.dest.dir}/python/platform_info.py
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/python.project2/nbproject/project.xml Tue Feb 24 01:58:36 2015 -0800
37.3 @@ -0,0 +1,162 @@
37.4 +<?xml version="1.0" encoding="UTF-8"?>
37.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
37.6 + <type>org.netbeans.modules.apisupport.project</type>
37.7 + <configuration>
37.8 + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
37.9 + <code-name-base>org.netbeans.modules.python.project2</code-name-base>
37.10 + <module-dependencies>
37.11 + <dependency>
37.12 + <code-name-base>org.netbeans.api.annotations.common</code-name-base>
37.13 + <build-prerequisite/>
37.14 + <compile-dependency/>
37.15 + <run-dependency>
37.16 + <release-version>1</release-version>
37.17 + <specification-version>1.25</specification-version>
37.18 + </run-dependency>
37.19 + </dependency>
37.20 + <dependency>
37.21 + <code-name-base>org.netbeans.api.java.classpath</code-name-base>
37.22 + <build-prerequisite/>
37.23 + <compile-dependency/>
37.24 + <run-dependency>
37.25 + <release-version>1</release-version>
37.26 + <specification-version>1.48</specification-version>
37.27 + </run-dependency>
37.28 + </dependency>
37.29 + <dependency>
37.30 + <code-name-base>org.netbeans.api.progress</code-name-base>
37.31 + <build-prerequisite/>
37.32 + <compile-dependency/>
37.33 + <run-dependency>
37.34 + <release-version>1</release-version>
37.35 + <specification-version>1.40</specification-version>
37.36 + </run-dependency>
37.37 + </dependency>
37.38 + <dependency>
37.39 + <code-name-base>org.netbeans.modules.projectapi</code-name-base>
37.40 + <build-prerequisite/>
37.41 + <compile-dependency/>
37.42 + <run-dependency>
37.43 + <release-version>1</release-version>
37.44 + <specification-version>1.62</specification-version>
37.45 + </run-dependency>
37.46 + </dependency>
37.47 + <dependency>
37.48 + <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
37.49 + <build-prerequisite/>
37.50 + <compile-dependency/>
37.51 + <run-dependency>
37.52 + <release-version>1</release-version>
37.53 + <specification-version>1.79</specification-version>
37.54 + </run-dependency>
37.55 + </dependency>
37.56 + <dependency>
37.57 + <code-name-base>org.netbeans.modules.python.core</code-name-base>
37.58 + <build-prerequisite/>
37.59 + <compile-dependency/>
37.60 + <run-dependency>
37.61 + <specification-version>1.0</specification-version>
37.62 + </run-dependency>
37.63 + </dependency>
37.64 + <dependency>
37.65 + <code-name-base>org.netbeans.modules.python.editor</code-name-base>
37.66 + <build-prerequisite/>
37.67 + <compile-dependency/>
37.68 + <run-dependency>
37.69 + <specification-version>1.0</specification-version>
37.70 + </run-dependency>
37.71 + </dependency>
37.72 + <dependency>
37.73 + <code-name-base>org.netbeans.modules.python.source</code-name-base>
37.74 + <build-prerequisite/>
37.75 + <compile-dependency/>
37.76 + <run-dependency>
37.77 + <specification-version>1.0</specification-version>
37.78 + </run-dependency>
37.79 + </dependency>
37.80 + <dependency>
37.81 + <code-name-base>org.netbeans.modules.queries</code-name-base>
37.82 + <build-prerequisite/>
37.83 + <compile-dependency/>
37.84 + <run-dependency>
37.85 + <release-version>1</release-version>
37.86 + <specification-version>1.39.1</specification-version>
37.87 + </run-dependency>
37.88 + </dependency>
37.89 + <dependency>
37.90 + <code-name-base>org.openide.actions</code-name-base>
37.91 + <build-prerequisite/>
37.92 + <compile-dependency/>
37.93 + <run-dependency>
37.94 + <specification-version>6.8.0.1</specification-version>
37.95 + </run-dependency>
37.96 + </dependency>
37.97 + <dependency>
37.98 + <code-name-base>org.openide.awt</code-name-base>
37.99 + <build-prerequisite/>
37.100 + <compile-dependency/>
37.101 + <run-dependency>
37.102 + <specification-version>7.62.1</specification-version>
37.103 + </run-dependency>
37.104 + </dependency>
37.105 + <dependency>
37.106 + <code-name-base>org.openide.dialogs</code-name-base>
37.107 + <build-prerequisite/>
37.108 + <compile-dependency/>
37.109 + <run-dependency>
37.110 + <specification-version>7.6</specification-version>
37.111 + </run-dependency>
37.112 + </dependency>
37.113 + <dependency>
37.114 + <code-name-base>org.openide.filesystems</code-name-base>
37.115 + <build-prerequisite/>
37.116 + <compile-dependency/>
37.117 + <run-dependency>
37.118 + <specification-version>9.0</specification-version>
37.119 + </run-dependency>
37.120 + </dependency>
37.121 + <dependency>
37.122 + <code-name-base>org.openide.loaders</code-name-base>
37.123 + <build-prerequisite/>
37.124 + <compile-dependency/>
37.125 + <run-dependency>
37.126 + <specification-version>7.61</specification-version>
37.127 + </run-dependency>
37.128 + </dependency>
37.129 + <dependency>
37.130 + <code-name-base>org.openide.nodes</code-name-base>
37.131 + <build-prerequisite/>
37.132 + <compile-dependency/>
37.133 + <run-dependency>
37.134 + <specification-version>7.39.1</specification-version>
37.135 + </run-dependency>
37.136 + </dependency>
37.137 + <dependency>
37.138 + <code-name-base>org.openide.util</code-name-base>
37.139 + <build-prerequisite/>
37.140 + <compile-dependency/>
37.141 + <run-dependency>
37.142 + <specification-version>9.3</specification-version>
37.143 + </run-dependency>
37.144 + </dependency>
37.145 + <dependency>
37.146 + <code-name-base>org.openide.util.lookup</code-name-base>
37.147 + <build-prerequisite/>
37.148 + <compile-dependency/>
37.149 + <run-dependency>
37.150 + <specification-version>8.25.1</specification-version>
37.151 + </run-dependency>
37.152 + </dependency>
37.153 + <dependency>
37.154 + <code-name-base>org.openide.windows</code-name-base>
37.155 + <build-prerequisite/>
37.156 + <compile-dependency/>
37.157 + <run-dependency>
37.158 + <specification-version>6.71.1</specification-version>
37.159 + </run-dependency>
37.160 + </dependency>
37.161 + </module-dependencies>
37.162 + <public-packages/>
37.163 + </data>
37.164 + </configuration>
37.165 +</project>
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/Bundle.properties Tue Feb 24 01:58:36 2015 -0800
38.3 @@ -0,0 +1,2 @@
38.4 +OpenIDE-Module-Name=Python Project 2
38.5 +Templates/Project/Python/PythonProject2.xml=Python Project
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/Python2LogicalView.java Tue Feb 24 01:58:36 2015 -0800
39.3 @@ -0,0 +1,180 @@
39.4 +package org.netbeans.modules.python.project2;
39.5 +
39.6 +import java.awt.Image;
39.7 +import java.io.CharConversionException;
39.8 +import java.util.ArrayList;
39.9 +import java.util.List;
39.10 +import javax.swing.Action;
39.11 +import org.netbeans.api.project.FileOwnerQuery;
39.12 +import org.netbeans.api.project.Project;
39.13 +import org.netbeans.api.project.ProjectUtils;
39.14 +import org.netbeans.modules.python.project2.ui.ChangePackageViewTypeAction;
39.15 +import org.netbeans.modules.python.project2.ui.PackageView;
39.16 +import org.netbeans.spi.project.ActionProvider;
39.17 +import org.netbeans.spi.project.ui.LogicalViewProvider;
39.18 +import org.netbeans.spi.project.ui.support.CommonProjectActions;
39.19 +import org.netbeans.spi.project.ui.support.DefaultProjectOperations;
39.20 +import org.netbeans.spi.project.ui.support.NodeFactorySupport;
39.21 +import org.netbeans.spi.project.ui.support.ProjectSensitiveActions;
39.22 +import org.openide.actions.FindAction;
39.23 +import org.openide.filesystems.FileObject;
39.24 +import org.openide.filesystems.FileUtil;
39.25 +import org.openide.nodes.AbstractNode;
39.26 +import org.openide.nodes.Node;
39.27 +import org.openide.util.HelpCtx;
39.28 +import org.openide.util.ImageUtilities;
39.29 +import org.openide.util.NbBundle;
39.30 +import org.openide.util.Utilities;
39.31 +import org.openide.util.actions.SystemAction;
39.32 +import org.openide.util.lookup.Lookups;
39.33 +import org.openide.xml.XMLUtil;
39.34 +import static org.netbeans.modules.python.project2.Bundle.*;
39.35 +
39.36 +/**
39.37 + *
39.38 + * @author alley
39.39 + * @author Tomas Zezula
39.40 + */
39.41 +@NbBundle.Messages({"# {0} - Path to of project",
39.42 + "PythonLogicalView.ProjectTooltipDescription=Python project in {0}",
39.43 + "LBL_RunAction_Name=Run",
39.44 + "LBL_DebugAction_Name=Debug",
39.45 + "LBL_TestAction_Name=Test",
39.46 + "LBL_BuildAction_Name=Build Egg",
39.47 + "LBL_CleanBuildAction_Name=Clean and Build Egg"})
39.48 +class Python2LogicalView implements LogicalViewProvider {
39.49 +
39.50 + private static final Image brokenProjectBadge = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/brokenProjectBadge.gif", true);
39.51 + private final PythonProject2 project;
39.52 +
39.53 + public Python2LogicalView(PythonProject2 project) {
39.54 + this.project = project;
39.55 + }
39.56 +
39.57 + @Override
39.58 + public Node createLogicalView() {
39.59 + return new PythonProjectNode();
39.60 + }
39.61 +
39.62 + @Override
39.63 + public Node findPath(Node root, Object target) {
39.64 + Project p = root.getLookup().lookup(Project.class);
39.65 + if (p == null) {
39.66 + return null;
39.67 + }
39.68 + if (target instanceof FileObject) {
39.69 + FileObject targetFO = (FileObject) target;
39.70 + Project owner = FileOwnerQuery.getOwner(targetFO);
39.71 + if (!p.equals(owner)) {
39.72 + return null; // Don't waste time if project does not own the fo
39.73 + }
39.74 +
39.75 + for (Node n : root.getChildren().getNodes(true)) {
39.76 + Node result = PackageView.findPath(n, target);
39.77 + if (result != null) {
39.78 + return result;
39.79 + }
39.80 + }
39.81 + }
39.82 +
39.83 + return null;
39.84 + }
39.85 +
39.86 + private final class PythonProjectNode extends AbstractNode {
39.87 +
39.88 + private boolean broken; //for future use, marks the project as broken
39.89 +
39.90 + public PythonProjectNode() {
39.91 + super(NodeFactorySupport.createCompositeChildren(project, "Projects/org-netbeans-modules-python-project2/Nodes"),
39.92 + Lookups.singleton(project));
39.93 + setIconBaseWithExtension("org/netbeans/modules/python/project2/resources/py_25_16.png");
39.94 + super.setName(ProjectUtils.getInformation(project).getDisplayName());
39.95 + }
39.96 +
39.97 + public
39.98 + @Override
39.99 + String getShortDescription() {
39.100 + //todo: Add python platform description
39.101 + String dirName = FileUtil.getFileDisplayName(project.getProjectDirectory());
39.102 + return PythonLogicalView_ProjectTooltipDescription(dirName);
39.103 + }
39.104 +
39.105 + public
39.106 + @Override
39.107 + String getHtmlDisplayName() {
39.108 + String dispName = super.getDisplayName();
39.109 + try {
39.110 + dispName = XMLUtil.toElementContent(dispName);
39.111 + } catch (CharConversionException ex) {
39.112 + return dispName;
39.113 + }
39.114 + // XXX text colors should be taken from UIManager, not hard-coded!
39.115 + return broken ? "<font color=\"#A40000\">" + dispName + "</font>" : null; //NOI18N
39.116 + }
39.117 +
39.118 + @Override
39.119 + public Image getIcon(int type) {
39.120 + Image original = super.getIcon(type);
39.121 + return broken ? ImageUtilities.mergeImages(original, brokenProjectBadge, 8, 0) : original;
39.122 + }
39.123 +
39.124 + @Override
39.125 + public Image getOpenedIcon(int type) {
39.126 + Image original = super.getOpenedIcon(type);
39.127 + return broken ? ImageUtilities.mergeImages(original, brokenProjectBadge, 8, 0) : original;
39.128 + }
39.129 +
39.130 + @Override
39.131 + public Action[] getActions(boolean context) {
39.132 + return getAdditionalActions();
39.133 + }
39.134 +
39.135 + @Override
39.136 + public boolean canRename() {
39.137 + return true;
39.138 + }
39.139 +
39.140 + @Override
39.141 + public void setName(String s) {
39.142 + DefaultProjectOperations.performDefaultRenameOperation(project, s);
39.143 + }
39.144 +
39.145 + @Override
39.146 + public HelpCtx getHelpCtx() {
39.147 + return new HelpCtx(PythonProjectNode.class);
39.148 + }
39.149 +
39.150 + private Action[] getAdditionalActions() {
39.151 + final List<Action> actions = new ArrayList<>();
39.152 + actions.add(CommonProjectActions.newFileAction());
39.153 + actions.add(null);
39.154 + actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_RUN, LBL_RunAction_Name(), null)); // NOI18N
39.155 + actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_DEBUG, LBL_DebugAction_Name(), null)); // NOI18N
39.156 +// actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_TEST, LBL_TestAction_Name(), null)); // NOI18N
39.157 + actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_BUILD, LBL_BuildAction_Name(), null)); // NOI18N
39.158 + actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_REBUILD, LBL_CleanBuildAction_Name(), null)); // NOI18N
39.159 + actions.add(null);
39.160 +// actions.add(CoverageActionFactory.createCollectorAction(null, null));
39.161 +// actions.add(null);
39.162 + actions.add(CommonProjectActions.setAsMainProjectAction());
39.163 + actions.add(CommonProjectActions.openSubprojectsAction());
39.164 + actions.add(CommonProjectActions.closeProjectAction());
39.165 + actions.add(null);
39.166 + actions.add(CommonProjectActions.renameProjectAction());
39.167 + actions.add(CommonProjectActions.moveProjectAction());
39.168 + actions.add(CommonProjectActions.copyProjectAction());
39.169 + actions.add(CommonProjectActions.deleteProjectAction());
39.170 + actions.add(null);
39.171 + actions.add(new ChangePackageViewTypeAction());
39.172 + actions.add(null);
39.173 + actions.add(SystemAction.get(FindAction.class));
39.174 +
39.175 + // honor 57874 contact
39.176 + actions.addAll(Utilities.actionsForPath("Projects/Actions")); //NOI18N
39.177 +
39.178 + actions.add(null);
39.179 + actions.add(CommonProjectActions.customizeProjectAction());
39.180 + return actions.toArray(new Action[actions.size()]);
39.181 + }
39.182 + }
39.183 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonActionProvider.java Tue Feb 24 01:58:36 2015 -0800
40.3 @@ -0,0 +1,93 @@
40.4 +package org.netbeans.modules.python.project2;
40.5 +
40.6 +import java.util.LinkedHashMap;
40.7 +import java.util.Map;
40.8 +import java.util.Set;
40.9 +import org.netbeans.modules.python.project2.ui.actions.Command;
40.10 +import org.netbeans.modules.python.project2.ui.actions.RunCommand;
40.11 +import org.netbeans.modules.python.project2.ui.actions.RunSingleCommand;
40.12 +import org.netbeans.spi.project.ActionProvider;
40.13 +import org.openide.LifecycleManager;
40.14 +import org.openide.util.Lookup;
40.15 +import org.openide.util.RequestProcessor;
40.16 +
40.17 +/**
40.18 + *
40.19 + * @author alley
40.20 + * @author Tomas Zezula
40.21 + */
40.22 +public class PythonActionProvider implements ActionProvider {
40.23 +
40.24 + private final Map<String, Command> commands;
40.25 +
40.26 + public PythonActionProvider(PythonProject2 project) {
40.27 + assert project != null;
40.28 + commands = new LinkedHashMap<String, Command>();
40.29 + Command[] commandArray = new Command[]{
40.30 + // new DeleteCommand(project),
40.31 + // new CopyCommand(project),
40.32 + // new MoveCommand(project),
40.33 + // new RenameCommand(project),
40.34 + // new CleanCommand(project),
40.35 + new RunSingleCommand(project, false),
40.36 + new RunSingleCommand(project, true), // Run as Test
40.37 + new RunCommand(project, false),
40.38 + new RunCommand(project, true), // Run project as Test
40.39 + // new DebugCommand(project) ,
40.40 + // new DebugSingleCommand(project, false),
40.41 + // new DebugSingleCommand(project, true), // Debug as Test
40.42 + // new BuildCommand(project), //Build Egg
40.43 + // new CleanBuildCommand(project) //Clean and Build Egg
40.44 + };
40.45 + for (Command command : commandArray) {
40.46 + commands.put(command.getCommandId(), command);
40.47 + }
40.48 + }
40.49 +
40.50 +// public static TestRunner getTestRunner(TestRunner.TestType testType) {
40.51 +// Collection<? extends TestRunner> testRunners = Lookup.getDefault().lookupAll(TestRunner.class);
40.52 +// for (TestRunner each : testRunners) {
40.53 +// if (each.supports(testType)) {
40.54 +// return each;
40.55 +// }
40.56 +// }
40.57 +// return null;
40.58 +// }
40.59 + @Override
40.60 + public String[] getSupportedActions() {
40.61 + final Set<String> names = commands.keySet();
40.62 + return names.toArray(new String[names.size()]);
40.63 + }
40.64 +
40.65 + @Override
40.66 + public void invokeAction(final String commandName, final Lookup context) throws IllegalArgumentException {
40.67 + final Command command = findCommand(commandName);
40.68 + assert command != null;
40.69 + if (command.saveRequired()) {
40.70 + LifecycleManager.getDefault().saveAll();
40.71 + }
40.72 + if (!command.asyncCallRequired()) {
40.73 + command.invokeAction(context);
40.74 + } else {
40.75 + RequestProcessor.getDefault().post(new Runnable() {
40.76 + @Override
40.77 + public void run() {
40.78 + command.invokeAction(context);
40.79 + }
40.80 + });
40.81 + }
40.82 + }
40.83 +
40.84 + @Override
40.85 + public boolean isActionEnabled(String commandName, Lookup context) throws IllegalArgumentException {
40.86 + final Command command = findCommand(commandName);
40.87 + assert command != null;
40.88 + return command.isActionEnabled(context);
40.89 + }
40.90 +
40.91 + private Command findCommand(final String commandName) {
40.92 + assert commandName != null;
40.93 + return commands.get(commandName);
40.94 + }
40.95 +
40.96 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonAuxilaryConfig.java Tue Feb 24 01:58:36 2015 -0800
41.3 @@ -0,0 +1,524 @@
41.4 +/*
41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
41.6 + *
41.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
41.8 + *
41.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
41.10 + * Other names may be trademarks of their respective owners.
41.11 + *
41.12 + * The contents of this file are subject to the terms of either the GNU
41.13 + * General Public License Version 2 only ("GPL") or the Common
41.14 + * Development and Distribution License("CDDL") (collectively, the
41.15 + * "License"). You may not use this file except in compliance with the
41.16 + * License. You can obtain a copy of the License at
41.17 + * http://www.netbeans.org/cddl-gplv2.html
41.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
41.19 + * specific language governing permissions and limitations under the
41.20 + * License. When distributing the software, include this License Header
41.21 + * Notice in each file and include the License file at
41.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
41.23 + * particular file as subject to the "Classpath" exception as provided
41.24 + * by Oracle in the GPL Version 2 section of the License file that
41.25 + * accompanied this code. If applicable, add the following below the
41.26 + * License Header, with the fields enclosed by brackets [] replaced by
41.27 + * your own identifying information:
41.28 + * "Portions Copyrighted [year] [name of copyright owner]"
41.29 + *
41.30 + * If you wish your version of this file to be governed by only the CDDL
41.31 + * or only the GPL Version 2, indicate your decision by adding
41.32 + * "[Contributor] elects to include this software in this distribution
41.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
41.34 + * single choice of license, a recipient has the option to distribute
41.35 + * your version of this file under either the CDDL, the GPL Version 2 or
41.36 + * to extend the choice of license to its licensees as provided above.
41.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
41.38 + * Version 2 license, then the option applies only if the new code is
41.39 + * made subject to such option by the copyright holder.
41.40 + *
41.41 + * Contributor(s):
41.42 + *
41.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
41.44 + */
41.45 +
41.46 +package org.netbeans.modules.python.project2;
41.47 +
41.48 +import java.beans.PropertyChangeListener;
41.49 +import java.beans.PropertyChangeSupport;
41.50 +import java.io.ByteArrayOutputStream;
41.51 +import java.io.IOException;
41.52 +import java.io.OutputStream;
41.53 +import java.io.StringReader;
41.54 +import java.util.Collection;
41.55 +import java.util.Collections;
41.56 +import java.util.HashSet;
41.57 +import java.util.Set;
41.58 +import java.util.concurrent.atomic.AtomicBoolean;
41.59 +import java.util.logging.Level;
41.60 +import java.util.logging.Logger;
41.61 +import javax.xml.parsers.DocumentBuilder;
41.62 +import javax.xml.parsers.DocumentBuilderFactory;
41.63 +import javax.xml.parsers.ParserConfigurationException;
41.64 +import org.netbeans.api.annotations.common.NonNull;
41.65 +import static org.netbeans.modules.python.project2.Bundle.*;
41.66 +import org.netbeans.spi.project.AuxiliaryConfiguration;
41.67 +import org.netbeans.spi.project.ui.ProjectProblemsProvider;
41.68 +import org.netbeans.spi.project.ui.ProjectProblemsProvider.ProjectProblem;
41.69 +import org.openide.filesystems.FileChangeAdapter;
41.70 +import org.openide.filesystems.FileEvent;
41.71 +import org.openide.filesystems.FileObject;
41.72 +import org.openide.filesystems.FileRenameEvent;
41.73 +import org.openide.filesystems.FileSystem.AtomicAction;
41.74 +import org.openide.filesystems.FileUtil;
41.75 +import org.openide.util.Exceptions;
41.76 +import org.openide.util.NbBundle.Messages;
41.77 +import org.openide.util.RequestProcessor;
41.78 +import org.openide.xml.XMLUtil;
41.79 +import org.w3c.dom.DOMException;
41.80 +import org.w3c.dom.Document;
41.81 +import org.w3c.dom.Element;
41.82 +import org.w3c.dom.Node;
41.83 +import org.w3c.dom.NodeList;
41.84 +import org.xml.sax.InputSource;
41.85 +import org.xml.sax.SAXException;
41.86 +
41.87 +/**
41.88 + * implementation of AuxiliaryConfiguration that relies on FileObject's attributes
41.89 + * for the non shared elements and on ${basedir}/nb-configuration file for share ones.
41.90 + * @author mkleint
41.91 + */
41.92 +public class PythonAuxilaryConfig implements AuxiliaryConfiguration {
41.93 + public static final String BROKEN_NBCONFIG = "BROKENNBCONFIG"; //NOI18N
41.94 +
41.95 + private static final String AUX_CONFIG = "AuxilaryConfiguration"; //NOI18N
41.96 + public static final String CONFIG_FILE_NAME = "nb-configuration.xml"; //NOI18N
41.97 +
41.98 + private static final Logger LOG = Logger.getLogger(PythonAuxilaryConfig.class.getName());
41.99 + private static final RequestProcessor RP = new RequestProcessor(PythonAuxilaryConfig.class);
41.100 + private static final int SAVING_DELAY = 100;
41.101 + private RequestProcessor.Task savingTask;
41.102 + private Document scheduledDocument;
41.103 + private Document cachedDoc;
41.104 + private static final Document DELETED_FILE_DOCUMENT = XMLUtil.createDocument(AUX_CONFIG, null, null, null);
41.105 + private static final Document BROKEN_DOCUMENT = XMLUtil.createDocument(AUX_CONFIG, null, null, null);
41.106 + private final Object configIOLock = new Object();
41.107 + private final FileObject projectDirectory;
41.108 + private ProblemProvider pp;
41.109 + private final FileChangeAdapter fileChange;
41.110 + private final AtomicBoolean fileChangeSet = new AtomicBoolean(false);
41.111 +
41.112 + public PythonAuxilaryConfig(FileObject dir, boolean longtermInstance) {
41.113 + this.projectDirectory = dir;
41.114 +
41.115 + if (longtermInstance) {
41.116 + pp = new ProblemProvider();
41.117 + fileChange = new FileChangeAdapter() {
41.118 +
41.119 + @Override
41.120 + public void fileRenamed(FileRenameEvent fe) {
41.121 + if (CONFIG_FILE_NAME.equals(fe.getName() + "." + fe.getExt())) {
41.122 + resetCache();
41.123 + }
41.124 + }
41.125 +
41.126 + @Override
41.127 + public void fileDeleted(FileEvent fe) {
41.128 + if (CONFIG_FILE_NAME.equals(fe.getFile().getNameExt())) {
41.129 + resetCache();
41.130 + }
41.131 + }
41.132 +
41.133 + @Override
41.134 + public void fileChanged(FileEvent fe) {
41.135 + if (CONFIG_FILE_NAME.equals(fe.getFile().getNameExt())) {
41.136 + resetCache();
41.137 + }
41.138 + }
41.139 +
41.140 + @Override
41.141 + public void fileDataCreated(FileEvent fe) {
41.142 + if (CONFIG_FILE_NAME.equals(fe.getFile().getNameExt())) {
41.143 + resetCache();
41.144 + }
41.145 + }
41.146 + };
41.147 +
41.148 + savingTask = RP.create(new Runnable() {
41.149 + public @Override void run() {
41.150 + try {
41.151 + projectDirectory.getFileSystem().runAtomicAction(new AtomicAction() {
41.152 + public @Override void run() throws IOException {
41.153 + Document doc;
41.154 + synchronized (PythonAuxilaryConfig.this) {
41.155 + doc = scheduledDocument;
41.156 + if (doc == null) {
41.157 + return;
41.158 + }
41.159 + scheduledDocument = null;
41.160 + }
41.161 + synchronized (configIOLock) {
41.162 + FileObject config = projectDirectory.getFileObject(CONFIG_FILE_NAME);
41.163 + if (doc.getDocumentElement().getElementsByTagName("*").getLength() > 0) {
41.164 + OutputStream out = config == null ? projectDirectory.createAndOpen(CONFIG_FILE_NAME) : config.getOutputStream();
41.165 + LOG.log(Level.FINEST, "Write configuration file for {0}", projectDirectory);
41.166 + try {
41.167 + XMLUtil.write(doc, out, "UTF-8"); //NOI18N
41.168 + } finally {
41.169 + out.close();
41.170 + }
41.171 + } else if (config != null) {
41.172 + LOG.log(Level.FINEST, "Delete empty configuration file for {0}", projectDirectory);
41.173 + config.delete();
41.174 + }
41.175 + }
41.176 + }
41.177 + });
41.178 + } catch (IOException ex) {
41.179 + LOG.log(Level.INFO, "IO Error while saving " + projectDirectory.getFileObject(CONFIG_FILE_NAME), ex);
41.180 + }
41.181 + }
41.182 + });
41.183 + } else {
41.184 + fileChange = null;
41.185 + fileChangeSet.set(true);
41.186 + }
41.187 + }
41.188 +
41.189 + private synchronized void resetCache() {
41.190 + cachedDoc = null;
41.191 + }
41.192 +
41.193 +
41.194 + public ProjectProblemsProvider getProblemProvider() {
41.195 + return pp;
41.196 + }
41.197 +
41.198 + private Document loadConfig(FileObject config) throws IOException, SAXException {
41.199 + synchronized (configIOLock) {
41.200 + return XMLUtil.parse(new InputSource(config.toURL().toString()), false, true, null, null);
41.201 + }
41.202 + }
41.203 +
41.204 + public @Override Element getConfigurationFragment(String elementName, String namespace, boolean shared) {
41.205 + Element e = doGetConfigurationFragment(elementName, namespace, shared);
41.206 + return e != null ? cloneSafely(e) : null;
41.207 + }
41.208 + // Copied from AntProjectHelper.
41.209 + private static final DocumentBuilder db;
41.210 + static {
41.211 + try {
41.212 + db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
41.213 + } catch (ParserConfigurationException e) {
41.214 + throw new AssertionError(e);
41.215 + }
41.216 + }
41.217 + private static Element cloneSafely(Element el) { // #190845
41.218 + // #50198: for thread safety, use a separate document.
41.219 + // Using XMLUtil.createDocument is much too slow.
41.220 + synchronized (db) {
41.221 + Document dummy = db.newDocument();
41.222 + return (Element) dummy.importNode(el, true);
41.223 + }
41.224 + }
41.225 + @Messages({
41.226 + "TXT_Problem_Broken_Config=Broken nb-configuration.xml file.",
41.227 + "# {0} - parser error message",
41.228 + "DESC_Problem_Broken_Config=The $project_basedir/nb-configuration.xml file cannot be parsed. "
41.229 + + "The information contained in the file will be ignored until fixed. "
41.230 + + "This affects several features in the IDE that will not work properly as a result.\n\n "
41.231 + + "The parsing exception follows:\n{0}",
41.232 + "TXT_Problem_Broken_Config2=Duplicate entries found in nb-configuration.xml file.",
41.233 + "DESC_Problem_Broken_Config2=The $project_basedir/nb-configuration.xml file contains some elements multiple times. "
41.234 + + "That can happen when concurrent changes get merged by version control for example. The IDE however cannot decide which one to use. "
41.235 + + "So until the problem is resolved manually, the affected configuration will be ignored."
41.236 + })
41.237 + private synchronized Element doGetConfigurationFragment(final String elementName, final String namespace, boolean shared) {
41.238 + lazyAttachListener();
41.239 + if (shared) {
41.240 + //first check the document schedule for persistence
41.241 + if (scheduledDocument != null) {
41.242 + try {
41.243 + Element el = XMLUtil.findElement(scheduledDocument.getDocumentElement(), elementName, namespace);
41.244 + if (el != null) {
41.245 + el = (Element) el.cloneNode(true);
41.246 + }
41.247 + return el;
41.248 + } catch (IllegalArgumentException iae) {
41.249 + //thrown from XmlUtil.findElement when more than 1 equal elements are present.
41.250 + LOG.log(Level.INFO, iae.getMessage(), iae);
41.251 + }
41.252 + }
41.253 + if (cachedDoc == null) {
41.254 + final FileObject config = projectDirectory.getFileObject(CONFIG_FILE_NAME);
41.255 + if (config != null) {
41.256 + // we need to re-read the config file..
41.257 + try {
41.258 + Document doc = loadConfig(config);
41.259 + cachedDoc = doc;
41.260 + if (pp != null) {
41.261 + pp.setProblem(null);
41.262 + findDuplicateElements(doc.getDocumentElement(), pp, config);
41.263 + }
41.264 + return XMLUtil.findElement(doc.getDocumentElement(), elementName, namespace);
41.265 + } catch (final SAXException ex) {
41.266 + if (pp != null) {
41.267 + RP.post(new Runnable() {
41.268 + @Override
41.269 + public void run() {
41.270 + pp.setProblem(ProjectProblem.createWarning(
41.271 + TXT_Problem_Broken_Config(),
41.272 + DESC_Problem_Broken_Config(ex.getMessage())/*,
41.273 + new ProblemReporterImpl.MavenProblemResolver(ProblemReporterImpl.createOpenFileAction(config), BROKEN_NBCONFIG)*/));
41.274 + }
41.275 + });
41.276 + }
41.277 + LOG.log(Level.INFO, ex.getMessage(), ex);
41.278 + cachedDoc = BROKEN_DOCUMENT;
41.279 + } catch (IOException ex) {
41.280 + LOG.log(Level.INFO, "IO Error while loading " + config.getPath(), ex);
41.281 + cachedDoc = BROKEN_DOCUMENT;
41.282 + } catch (IllegalArgumentException iae) {
41.283 + //thrown from XmlUtil.findElement when more than 1 equal elements are present.
41.284 + LOG.log(Level.INFO, iae.getMessage(), iae);
41.285 + }
41.286 + return null;
41.287 + } else {
41.288 + // no file.. remove possible cache
41.289 + cachedDoc = DELETED_FILE_DOCUMENT;
41.290 + return null;
41.291 + }
41.292 + } else {
41.293 + if (cachedDoc == DELETED_FILE_DOCUMENT || cachedDoc == BROKEN_DOCUMENT) {
41.294 + return null;
41.295 + }
41.296 + //reuse cached value if available;
41.297 + try {
41.298 + return XMLUtil.findElement(cachedDoc.getDocumentElement(), elementName, namespace);
41.299 + } catch (IllegalArgumentException iae) {
41.300 + //thrown from XmlUtil.findElement when more than 1 equal elements are present.
41.301 + LOG.log(Level.INFO, iae.getMessage(), iae);
41.302 + }
41.303 + }
41.304 + return null;
41.305 + } else {
41.306 + String str = (String) projectDirectory.getAttribute(AUX_CONFIG);
41.307 + if (str != null) {
41.308 + Document doc;
41.309 + try {
41.310 + doc = XMLUtil.parse(new InputSource(new StringReader(str)), false, true, null, null);
41.311 + return XMLUtil.findElement(doc.getDocumentElement(), elementName, namespace);
41.312 + } catch (SAXException ex) {
41.313 + LOG.log(Level.FINE, "cannot parse", ex);
41.314 + } catch (IOException ex) {
41.315 + LOG.log(Level.FINE, "error reading private auxiliary configuration", ex);
41.316 + }
41.317 + }
41.318 + return null;
41.319 + }
41.320 + }
41.321 +
41.322 + private void lazyAttachListener() {
41.323 + if (fileChangeSet.compareAndSet(false, true)) {
41.324 + projectDirectory.addFileChangeListener(FileUtil.weakFileChangeListener(fileChange, projectDirectory));
41.325 + }
41.326 + }
41.327 +
41.328 + public @Override synchronized void putConfigurationFragment(final Element fragment, final boolean shared) throws IllegalArgumentException {
41.329 + lazyAttachListener();
41.330 + Document doc = null;
41.331 + if (shared) {
41.332 + if (scheduledDocument != null) {
41.333 + doc = scheduledDocument;
41.334 + } else {
41.335 + FileObject config = projectDirectory.getFileObject(CONFIG_FILE_NAME);
41.336 + if (config != null) {
41.337 + try {
41.338 + doc = loadConfig(config);
41.339 + } catch (SAXException ex) {
41.340 + LOG.log(Level.INFO, "Cannot parse file " + config.getPath(), ex);
41.341 + if (config.getSize() == 0) {
41.342 + //something got wrong in the past..
41.343 + doc = createNewSharedDocument();
41.344 + }
41.345 + } catch (IOException ex) {
41.346 + LOG.log(Level.INFO, "IO Error with " + config.getPath(), ex);
41.347 + }
41.348 + } else {
41.349 + doc = createNewSharedDocument();
41.350 + }
41.351 + }
41.352 + } else {
41.353 + String str = (String) projectDirectory.getAttribute(AUX_CONFIG);
41.354 + if (str != null) {
41.355 + try {
41.356 + doc = XMLUtil.parse(new InputSource(new StringReader(str)), false, true, null, null);
41.357 + } catch (SAXException ex) {
41.358 + LOG.log(Level.FINE, "cannot parse", ex);
41.359 + } catch (IOException ex) {
41.360 + LOG.log(Level.FINE, "error reading private auxiliary configuration", ex);
41.361 + }
41.362 + }
41.363 + if (doc == null) {
41.364 + String element = "project-private"; // NOI18N
41.365 + doc = XMLUtil.createDocument(element, null, null, null);
41.366 + }
41.367 + }
41.368 + if (doc != null) {
41.369 + Element el = XMLUtil.findElement(doc.getDocumentElement(), fragment.getNodeName(), fragment.getNamespaceURI());
41.370 + if (el != null) {
41.371 + doc.getDocumentElement().removeChild(el);
41.372 + }
41.373 + doc.getDocumentElement().appendChild(doc.importNode(fragment, true));
41.374 +
41.375 + if (shared) {
41.376 + if (scheduledDocument == null) {
41.377 + scheduledDocument = doc;
41.378 + }
41.379 + LOG.log(Level.FINEST, "Schedule saving of configuration fragment for " + projectDirectory, new Exception());
41.380 + savingTask.schedule(SAVING_DELAY);
41.381 + } else {
41.382 + try {
41.383 + ByteArrayOutputStream wr = new ByteArrayOutputStream();
41.384 + XMLUtil.write(doc, wr, "UTF-8"); //NOI18N
41.385 + projectDirectory.setAttribute(AUX_CONFIG, wr.toString("UTF-8"));
41.386 + } catch (IOException ex) {
41.387 + LOG.log(Level.FINE, "error writing private auxiliary configuration", ex);
41.388 + }
41.389 + }
41.390 + }
41.391 +
41.392 + }
41.393 +
41.394 + public @Override synchronized boolean removeConfigurationFragment(final String elementName, final String namespace, final boolean shared) throws IllegalArgumentException {
41.395 + lazyAttachListener();
41.396 + Document doc = null;
41.397 + FileObject config = projectDirectory.getFileObject(CONFIG_FILE_NAME);
41.398 + if (shared) {
41.399 + if (scheduledDocument != null) {
41.400 + doc = scheduledDocument;
41.401 + } else {
41.402 + if (config != null) {
41.403 + try {
41.404 + try {
41.405 + doc = loadConfig(config);
41.406 + } catch (SAXException ex) {
41.407 + LOG.log(Level.INFO, "Cannot parse file " + config.getPath(), ex);
41.408 + if (config.getSize() == 0) {
41.409 + //just delete the empty file, something got wrong a while back..
41.410 + config.delete();
41.411 + }
41.412 + return true;
41.413 + }
41.414 + } catch (IOException ex) {
41.415 + LOG.log(Level.INFO, "IO Error with " + config.getPath(), ex);
41.416 + }
41.417 + } else {
41.418 + return false;
41.419 + }
41.420 + }
41.421 + } else {
41.422 + String str = (String) projectDirectory.getAttribute(AUX_CONFIG);
41.423 + if (str != null) {
41.424 + try {
41.425 + doc = XMLUtil.parse(new InputSource(new StringReader(str)), false, true, null, null);
41.426 + } catch (SAXException ex) {
41.427 + Exceptions.printStackTrace(ex);
41.428 + } catch (IOException ex) {
41.429 + Exceptions.printStackTrace(ex);
41.430 + }
41.431 + } else {
41.432 + return false;
41.433 + }
41.434 + }
41.435 + if (doc != null) {
41.436 + Element el = XMLUtil.findElement(doc.getDocumentElement(), elementName, namespace);
41.437 + if (el != null) {
41.438 + doc.getDocumentElement().removeChild(el);
41.439 + }
41.440 + if (shared) {
41.441 + if (scheduledDocument == null) {
41.442 + scheduledDocument = doc;
41.443 + }
41.444 + LOG.log(Level.FINEST, "Schedule saving of configuration fragment for " + projectDirectory, new Exception());
41.445 + savingTask.schedule(SAVING_DELAY);
41.446 + } else {
41.447 + try {
41.448 + ByteArrayOutputStream wr = new ByteArrayOutputStream();
41.449 + XMLUtil.write(doc, wr, "UTF-8"); //NOI18N
41.450 + projectDirectory.setAttribute(AUX_CONFIG, wr.toString("UTF-8"));
41.451 + } catch (IOException ex) {
41.452 + Exceptions.printStackTrace(ex);
41.453 + }
41.454 + }
41.455 + }
41.456 + return true;
41.457 + }
41.458 +
41.459 + private Document createNewSharedDocument() throws DOMException {
41.460 + String element = "project-shared-configuration";
41.461 + Document doc = XMLUtil.createDocument(element, null, null, null);
41.462 + doc.getDocumentElement().appendChild(doc.createComment(
41.463 + "\nThis file contains additional configuration written by modules in the NetBeans IDE.\n" +
41.464 + "The configuration is intended to be shared among all the users of project and\n" +
41.465 + "therefore it is assumed to be part of version control checkout.\n" +
41.466 + "Without this configuration present, some functionality in the IDE may be limited or fail altogether.\n"));
41.467 + return doc;
41.468 + }
41.469 +
41.470 + static void findDuplicateElements(@NonNull Element parent, @NonNull ProblemProvider pp, FileObject config) {
41.471 + NodeList l = parent.getChildNodes();
41.472 + int nodeCount = l.getLength();
41.473 + Set<String> known = new HashSet<String>();
41.474 + for (int i = 0; i < nodeCount; i++) {
41.475 + if (l.item(i).getNodeType() == Node.ELEMENT_NODE) {
41.476 + Node node = l.item(i);
41.477 + String localName = node.getLocalName();
41.478 + localName = localName == null ? node.getNodeName() : localName;
41.479 + String id = localName + "|" + node.getNamespaceURI();
41.480 + if (!known.add(id)) {
41.481 + //we have a duplicate;
41.482 + pp.setProblem(ProjectProblem.createWarning(
41.483 + TXT_Problem_Broken_Config2(),
41.484 + DESC_Problem_Broken_Config2()/*,
41.485 + new ProblemReporterImpl.MavenProblemResolver(ProblemReporterImpl.createOpenFileAction(config), BROKEN_NBCONFIG)*/));
41.486 + }
41.487 + }
41.488 + }
41.489 + }
41.490 +
41.491 + private class ProblemProvider implements ProjectProblemsProvider {
41.492 +
41.493 + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
41.494 + private ProjectProblem pp;
41.495 +
41.496 + public ProblemProvider() {
41.497 + }
41.498 +
41.499 + void setProblem(ProjectProblem pp) {
41.500 + this.pp = pp;
41.501 + if (pp == null && this.pp == null) {
41.502 + return; //ignore this case, dont' fire change..
41.503 + }
41.504 + pcs.firePropertyChange(ProjectProblemsProvider.PROP_PROBLEMS, null, null);
41.505 + }
41.506 +
41.507 + @Override
41.508 + public void addPropertyChangeListener(PropertyChangeListener listener) {
41.509 + pcs.addPropertyChangeListener(listener);
41.510 + }
41.511 +
41.512 + @Override
41.513 + public void removePropertyChangeListener(PropertyChangeListener listener) {
41.514 + pcs.removePropertyChangeListener(listener);
41.515 + }
41.516 +
41.517 + @Override
41.518 + public Collection<? extends ProjectProblem> getProblems() {
41.519 + if (pp != null) {
41.520 + return Collections.singleton(pp);
41.521 + } else {
41.522 + return Collections.emptyList();
41.523 + }
41.524 + }
41.525 +
41.526 + }
41.527 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonProject2.java Tue Feb 24 01:58:36 2015 -0800
42.3 @@ -0,0 +1,368 @@
42.4 +package org.netbeans.modules.python.project2;
42.5 +
42.6 +import java.beans.PropertyChangeListener;
42.7 +import java.beans.PropertyChangeSupport;
42.8 +import java.io.IOException;
42.9 +import java.util.Properties;
42.10 +import java.util.Scanner;
42.11 +import java.util.concurrent.ExecutionException;
42.12 +import java.util.concurrent.Future;
42.13 +import javax.swing.Icon;
42.14 +import javax.swing.ImageIcon;
42.15 +import org.netbeans.api.project.Project;
42.16 +import org.netbeans.api.project.ProjectInformation;
42.17 +import org.netbeans.api.project.ProjectManager;
42.18 +import org.netbeans.api.project.ProjectUtils;
42.19 +import org.netbeans.modules.python.api.PythonException;
42.20 +import org.netbeans.modules.python.api.PythonExecution;
42.21 +import org.netbeans.modules.python.api.PythonPlatform;
42.22 +import org.netbeans.modules.python.api.PythonPlatformManager;
42.23 +import org.netbeans.modules.python.editor.codecoverage.PythonCoverageProvider;
42.24 +import org.netbeans.modules.python.project2.classpath.ClassPathProviderImpl;
42.25 +import org.netbeans.modules.python.project2.ui.customizer.PythonCustomizerProvider;
42.26 +import org.netbeans.spi.project.AuxiliaryConfiguration;
42.27 +import org.netbeans.spi.project.ProjectState;
42.28 +import org.netbeans.spi.project.ui.LogicalViewProvider;
42.29 +import org.netbeans.spi.project.ui.ProjectOpenedHook;
42.30 +import org.openide.filesystems.FileAttributeEvent;
42.31 +import org.openide.filesystems.FileChangeListener;
42.32 +import org.openide.filesystems.FileEvent;
42.33 +import org.openide.filesystems.FileObject;
42.34 +import org.openide.filesystems.FileRenameEvent;
42.35 +import org.openide.filesystems.FileUtil;
42.36 +import org.openide.util.Exceptions;
42.37 +import org.openide.util.ImageUtilities;
42.38 +import org.openide.util.Lookup;
42.39 +import org.openide.util.Mutex;
42.40 +import org.openide.util.io.ReaderInputStream;
42.41 +import org.openide.util.lookup.Lookups;
42.42 +import org.openide.xml.XMLUtil;
42.43 +import org.w3c.dom.Element;
42.44 +import org.w3c.dom.Node;
42.45 +import org.w3c.dom.NodeList;
42.46 +import org.w3c.dom.Text;
42.47 +
42.48 +/**
42.49 + *
42.50 + * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
42.51 + */
42.52 +public class PythonProject2 implements Project {
42.53 +
42.54 + /**
42.55 + * the only property change fired by the class, means that the setup.py file
42.56 + * has changed.
42.57 + */
42.58 + public static final String PROP_PROJECT = "MavenProject"; //NOI18N
42.59 +
42.60 + private static final String NS_PYTHON_1 = "http://nbpython.dev.java.net/ns/php-project/1"; // NOI18N
42.61 + private static final String EL_PYTHON = "python-data"; // NOI18N
42.62 + private static final ImageIcon PROJECT_ICON = ImageUtilities.loadImageIcon("org/netbeans/modules/python/project/resources/py_25_16.png", false);
42.63 +
42.64 + private static final String MAIN_MODULE = "main.file"; //NOI18N
42.65 + private static final String APPLICATION_ARGS = "application.args"; //NOI18N
42.66 + private static final String ACTIVE_PLATFORM = "platform.active"; //NOI18N
42.67 + public static final String SOURCES_TYPE_PYTHON = "python"; //NOI18N
42.68 + static final String SETUPPY = "setup.py"; //NOI18N
42.69 +
42.70 + private final FileObject projectDirectory;
42.71 + protected Lookup lkp;
42.72 + protected AuxiliaryConfiguration aux;
42.73 + protected LogicalViewProvider logicalView;
42.74 + private final Info info;
42.75 + private final PropertyChangeSupport support;
42.76 + private final PythonSources sources;
42.77 +
42.78 + public PythonProject2(FileObject projectDirectory, ProjectState state) {
42.79 + support = new PropertyChangeSupport(this);
42.80 + this.logicalView = new Python2LogicalView(this);
42.81 + this.projectDirectory = projectDirectory;
42.82 + info = new PythonProject2.Info();
42.83 + aux = new PythonAuxilaryConfig(projectDirectory, true);
42.84 + sources = new PythonSources(this);
42.85 + this.lkp = createLookup(state);
42.86 + }
42.87 +
42.88 + @Override
42.89 + public FileObject getProjectDirectory() {
42.90 + return projectDirectory;
42.91 + }
42.92 +
42.93 + @Override
42.94 + public Lookup getLookup() {
42.95 + return lkp;
42.96 + }
42.97 +
42.98 + private Lookup createLookup(ProjectState state) {
42.99 + return Lookups.fixed(new Object[]{
42.100 + this, //project spec requires a project be in it's own lookup
42.101 + aux, //Auxiliary configuartion to store bookmarks and so on
42.102 + new PythonActionProvider(this), //Provides Standard like build and cleen
42.103 + info, // Project information Implementation
42.104 + logicalView, // Logical view if project implementation
42.105 + new PythonProject2.PythonOpenedHook(), //Called by project framework when project is opened (closed)
42.106 + sources, //Python source grops - used by package view, factories, refactoring, ...
42.107 + new ClassPathProviderImpl(this, sources),
42.108 +// new PythonProjectOperations(this), //move, rename, copy of project
42.109 +// new PythonProject.RecommendedTemplatesImpl(this.updateHelper), // Recommended Templates
42.110 + new PythonCustomizerProvider(this), //Project custmoizer
42.111 +// new PythonProjectFileEncodingQuery(getEvaluator()), //Provides encoding of the project - used by editor, runtime
42.112 +// new PythonSharabilityQuery(helper, getEvaluator(), getSourceRoots(), getTestRoots()), //Sharabilit info - used by VCS
42.113 +// helper.createCacheDirectoryProvider(), //Cache provider
42.114 +// helper.createAuxiliaryProperties(), // AuxiliaryConfiguraion provider - used by bookmarks, project Preferences, etc
42.115 +// new PythonPlatformProvider(getEvaluator()),
42.116 + new PythonCoverageProvider(this),
42.117 + new PythonProjectSourceLevelQuery(this),
42.118 + state
42.119 + });
42.120 + }
42.121 +
42.122 + public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener) {
42.123 + support.addPropertyChangeListener(propertyChangeListener);
42.124 + }
42.125 +
42.126 + public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener) {
42.127 + support.removePropertyChangeListener(propertyChangeListener);
42.128 + }
42.129 +
42.130 + public PythonPlatform getActivePlatform() {
42.131 + String pid = getProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.APPLICATION_ARGS);
42.132 + final PythonPlatformManager manager = PythonPlatformManager.getInstance();
42.133 + if (pid == null) {
42.134 + pid = manager.getDefaultPlatform();
42.135 + }
42.136 + return manager.getPlatform(pid);
42.137 + }
42.138 +
42.139 + public void setActivePlatform(final PythonPlatform platform) {
42.140 + storeProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.ACTIVE_PLATFORM, platform.getId());
42.141 + }
42.142 +
42.143 + public String getApplicationArgs() {
42.144 + return getProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.APPLICATION_ARGS);
42.145 + }
42.146 +
42.147 + public void setApplicationArgs(final String args) {
42.148 + storeProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.APPLICATION_ARGS, args);
42.149 + }
42.150 +
42.151 + public String getMainModule() {
42.152 + return getProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.MAIN_MODULE);
42.153 + }
42.154 +
42.155 + public void setMainModule(final String main) {
42.156 + storeProp(ProjectUtils.getAuxiliaryConfiguration(this), PythonProject2.MAIN_MODULE, main);
42.157 + }
42.158 +
42.159 + private String getProp(final AuxiliaryConfiguration auxiliaryConfiguration, final String key) {
42.160 + return ProjectManager.mutex().readAccess(new Mutex.Action<String>() {
42.161 + @Override
42.162 + public String run() {
42.163 + Element data = auxiliaryConfiguration.getConfigurationFragment(PythonProject2.EL_PYTHON, PythonProject2.NS_PYTHON_1, true);
42.164 + if (data == null) {
42.165 + return null;
42.166 + }
42.167 + NodeList nl = data.getElementsByTagNameNS(PythonProject2.NS_PYTHON_1, key);
42.168 + if (nl.getLength() == 1) {
42.169 + nl = nl.item(0).getChildNodes();
42.170 + if (nl.getLength() == 1 && nl.item(0).getNodeType() == Node.TEXT_NODE) {
42.171 + return ((Text) nl.item(0)).getNodeValue();
42.172 + }
42.173 + }
42.174 + return null; // NOI18N
42.175 + }
42.176 + });
42.177 + }
42.178 +
42.179 + private void storeProp(final AuxiliaryConfiguration auxiliaryConfiguration, final String key, final String main) {
42.180 + ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
42.181 + @Override
42.182 + public Void run() {
42.183 + Element data = auxiliaryConfiguration.getConfigurationFragment(PythonProject2.EL_PYTHON, PythonProject2.NS_PYTHON_1, true);
42.184 + if (data == null) {
42.185 + data = XMLUtil.createDocument(PythonProject2.EL_PYTHON, PythonProject2.NS_PYTHON_1, null, null).getDocumentElement();
42.186 + auxiliaryConfiguration.putConfigurationFragment(data, false);
42.187 + }
42.188 + NodeList nl = data.getElementsByTagNameNS(PythonProject2.NS_PYTHON_1, key);
42.189 + Element nameEl;
42.190 + if (nl.getLength() == 1) {
42.191 + nameEl = (Element) nl.item(0);
42.192 + NodeList deadKids = nameEl.getChildNodes();
42.193 + while (deadKids.getLength() > 0) {
42.194 + nameEl.removeChild(deadKids.item(0));
42.195 + }
42.196 + } else {
42.197 + nameEl = data.getOwnerDocument().createElementNS(PythonProject2.NS_PYTHON_1, key);
42.198 + data.insertBefore(nameEl, data.getChildNodes().item(0));
42.199 + }
42.200 + nameEl.appendChild(data.getOwnerDocument().createTextNode(main));
42.201 + auxiliaryConfiguration.putConfigurationFragment(data, true);
42.202 + return null;
42.203 + }
42.204 + });
42.205 + }
42.206 +
42.207 + private final class Info implements ProjectInformation, FileChangeListener {
42.208 +
42.209 + private static final String PROP_VERSION = "version";
42.210 +
42.211 + private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
42.212 + private final Properties properties;
42.213 +
42.214 + public Info() {
42.215 + properties = findProjectProperties();
42.216 + }
42.217 +
42.218 + @Override
42.219 + public void addPropertyChangeListener(PropertyChangeListener listener) {
42.220 + propertyChangeSupport.addPropertyChangeListener(listener);
42.221 + }
42.222 +
42.223 + @Override
42.224 + public void removePropertyChangeListener(PropertyChangeListener listener) {
42.225 + propertyChangeSupport.removePropertyChangeListener(listener);
42.226 + }
42.227 +
42.228 + public Properties getProperties() {
42.229 + return properties;
42.230 + }
42.231 +
42.232 + @Override
42.233 + public String getDisplayName() {
42.234 + return properties.getProperty(PROP_DISPLAY_NAME);
42.235 + }
42.236 +
42.237 + @Override
42.238 + public Icon getIcon() {
42.239 + return PROJECT_ICON;
42.240 + }
42.241 +
42.242 + @Override
42.243 + public String getName() {
42.244 + return projectDirectory.getName();
42.245 +// return name;
42.246 + }
42.247 +
42.248 + public String getVersion() {
42.249 + return properties.getProperty(PROP_VERSION);
42.250 +// return version;
42.251 + }
42.252 +
42.253 + @Override
42.254 + public Project getProject() {
42.255 + return PythonProject2.this;
42.256 + }
42.257 +
42.258 + public Properties findProjectProperties() {
42.259 + Properties props = new Properties();
42.260 + PythonPlatform platform = PythonPlatformManager.getInstance().getPlatforms().get(0);
42.261 + PythonExecution pye;
42.262 + try {
42.263 + pye = new PythonExecution();
42.264 + pye.setCommand(platform.getInterpreterCommand());
42.265 + pye.setDisplayName("Python Project Info");
42.266 + FileObject setuppy = projectDirectory.getFileObject(SETUPPY);
42.267 + setuppy.addFileChangeListener(this);
42.268 + pye.setScript(FileUtil.toFile(setuppy).getAbsolutePath());
42.269 + pye.setScriptArgs("--name --version"); //NOI18N
42.270 + pye.setShowControls(false);
42.271 + pye.setShowInput(false);
42.272 + pye.setShowWindow(false);
42.273 + pye.setShowProgress(false);
42.274 + pye.setShowSuspended(false);
42.275 + //pye.setWorkingDirectory(info.getAbsolutePath().substring(0, info.getAbsolutePath().lastIndexOf(File.separator)));
42.276 + pye.setWorkingDirectory(FileUtil.toFile(projectDirectory).getAbsolutePath());
42.277 + pye.attachOutputProcessor();
42.278 + Future<Integer> result = pye.run();
42.279 + Integer value = result.get();
42.280 + if (value.intValue() == 0) {
42.281 + // Problem with encoding?
42.282 +// prop.load(new ReaderInputStream(pye.getOutput()));
42.283 + try (Scanner sc = new Scanner(new ReaderInputStream(pye.getOutput()))) {
42.284 + String newName = sc.nextLine();
42.285 + props.setProperty(PROP_DISPLAY_NAME, newName);
42.286 + String newVersion = sc.nextLine();
42.287 + props.setProperty(PROP_VERSION, newVersion);
42.288 + }
42.289 + } else {
42.290 + throw new PythonException("Could not discover Python Project Info");
42.291 + }
42.292 + } catch (PythonException | InterruptedException | ExecutionException | IOException ex) {
42.293 + Exceptions.printStackTrace(ex);
42.294 + }
42.295 + return props;
42.296 + }
42.297 +
42.298 + @Override
42.299 + public void fileFolderCreated(FileEvent fe) {
42.300 + }
42.301 +
42.302 + @Override
42.303 + public void fileDataCreated(FileEvent fe) {
42.304 + }
42.305 +
42.306 + @Override
42.307 + public void fileChanged(FileEvent fe) {
42.308 + ProjectManager.mutex().writeAccess(new Mutex.Action<Void>() {
42.309 +
42.310 + @Override
42.311 + public Void run() {
42.312 + Properties newProps = findProjectProperties();
42.313 + for (String propName : newProps.stringPropertyNames()) {
42.314 + String value = newProps.getProperty(propName);
42.315 + Object oldValue = properties.setProperty(propName, value);
42.316 + if (!value.equals(oldValue)) {
42.317 + propertyChangeSupport.firePropertyChange(propName, oldValue, value);
42.318 + }
42.319 + }
42.320 + return null;
42.321 + }
42.322 + });
42.323 + }
42.324 +
42.325 + @Override
42.326 + public void fileDeleted(FileEvent fe) {
42.327 + //TODO: What when it is deleted?
42.328 + }
42.329 +
42.330 + @Override
42.331 + public void fileRenamed(FileRenameEvent fe) {
42.332 + //TODO: What when it is renamed?
42.333 + }
42.334 +
42.335 + @Override
42.336 + public void fileAttributeChanged(FileAttributeEvent fe) {
42.337 + }
42.338 + }
42.339 +
42.340 + public final class PythonOpenedHook extends ProjectOpenedHook {
42.341 +
42.342 + @Override
42.343 + protected void projectOpened() {
42.344 + // register project's classpaths to GlobalPathRegistry
42.345 +// final ClassPathProviderImpl cpProvider = getLookup().lookup(ClassPathProviderImpl.class);
42.346 +// assert cpProvider != null;
42.347 +// GlobalPathRegistry.getDefault().register(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
42.348 +// GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
42.349 +
42.350 + // Ensure that code coverage is initialized in case it's enabled...
42.351 +// PythonCoverageProvider codeCoverage = getLookup().lookup(PythonCoverageProvider.class);
42.352 +// if (codeCoverage.isEnabled()) {
42.353 +// codeCoverage.notifyProjectOpened();
42.354 +// }
42.355 + }
42.356 +
42.357 + @Override
42.358 + protected void projectClosed() {
42.359 + // unregister project's classpaths to GlobalPathRegistry
42.360 +// final ClassPathProviderImpl cpProvider = getLookup().lookup(ClassPathProviderImpl.class);
42.361 +// assert cpProvider != null;
42.362 +// //GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
42.363 +// GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
42.364 +// try {
42.365 +// ProjectManager.getDefault().saveProject(PythonProject2.this);
42.366 +// } catch (IOException e) {
42.367 +// Exceptions.printStackTrace(e);
42.368 +// }
42.369 + }
42.370 + }
42.371 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonProjectFactory.java Tue Feb 24 01:58:36 2015 -0800
43.3 @@ -0,0 +1,39 @@
43.4 +/*
43.5 + * To change this license header, choose License Headers in Project Properties.
43.6 + * To change this template file, choose Tools | Templates
43.7 + * and open the template in the editor.
43.8 + */
43.9 +package org.netbeans.modules.python.project2;
43.10 +
43.11 +import java.io.IOException;
43.12 +import org.netbeans.api.project.Project;
43.13 +import org.netbeans.spi.project.ProjectFactory;
43.14 +import org.netbeans.spi.project.ProjectState;
43.15 +import org.openide.filesystems.FileObject;
43.16 +import org.openide.util.lookup.ServiceProvider;
43.17 +
43.18 +/**
43.19 + *
43.20 + * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
43.21 + */
43.22 +@ServiceProvider(service=ProjectFactory.class)
43.23 +public class PythonProjectFactory implements ProjectFactory {
43.24 +
43.25 +
43.26 + @Override
43.27 + public boolean isProject(FileObject projectDirectory) {
43.28 + return projectDirectory.getFileObject(PythonProject2.SETUPPY) != null;
43.29 + }
43.30 +
43.31 + //Specifies when the project will be opened, i.e., if the project exists:
43.32 + @Override
43.33 + public Project loadProject(FileObject dir, ProjectState state) throws IOException {
43.34 + return isProject(dir) ? new PythonProject2(dir, state) : null;
43.35 + }
43.36 +
43.37 + @Override
43.38 + public void saveProject(final Project project) throws IOException, ClassCastException {
43.39 + // leave unimplemented for the moment
43.40 + }
43.41 +
43.42 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonProjectSourceLevelQuery.java Tue Feb 24 01:58:36 2015 -0800
44.3 @@ -0,0 +1,88 @@
44.4 +package org.netbeans.modules.python.project2;
44.5 +
44.6 +import java.beans.PropertyChangeEvent;
44.7 +import java.beans.PropertyChangeListener;
44.8 +import javax.swing.event.ChangeListener;
44.9 +import org.netbeans.api.annotations.common.CheckForNull;
44.10 +import org.netbeans.api.annotations.common.NonNull;
44.11 +import org.netbeans.api.project.ProjectUtils;
44.12 +import org.netbeans.modules.python.api.PythonPlatform;
44.13 +import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
44.14 +import org.openide.filesystems.FileObject;
44.15 +import org.openide.util.ChangeSupport;
44.16 +import org.openide.util.WeakListeners;
44.17 +
44.18 +/**
44.19 + *
44.20 + * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
44.21 + */
44.22 +class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
44.23 +
44.24 + private final PythonProject2 project;
44.25 + private final Result result;
44.26 +
44.27 + PythonProjectSourceLevelQuery(@NonNull final PythonProject2 project) {
44.28 + assert project != null;
44.29 + this.project = project;
44.30 + this.result = new R(project);
44.31 + }
44.32 +
44.33 + @Override
44.34 + public Result getSourceLevel(FileObject javaFile) {
44.35 + return this.result;
44.36 + }
44.37 +
44.38 + @CheckForNull
44.39 + static String findSourceLevel (@NonNull final PythonProject2 project) {
44.40 + return findValue(project);
44.41 + }
44.42 +
44.43 + @CheckForNull
44.44 + private static String findValue(
44.45 + @NonNull final PythonProject2 project) {
44.46 + final PythonPlatform activePlatform = project.getActivePlatform();
44.47 + return activePlatform.getSourceLevel();
44.48 + }
44.49 +
44.50 + private class R implements Result, PropertyChangeListener {
44.51 +
44.52 + private final ChangeSupport cs = new ChangeSupport(this);
44.53 +
44.54 + @SuppressWarnings("LeakingThisInConstructor")
44.55 + private R(final PythonProject2 project) {
44.56 + project.addPropertyChangeListener(WeakListeners.propertyChange(this, project));
44.57 + }
44.58 +
44.59 + @Override
44.60 + public String getSourceLevel() {
44.61 + return findSourceLevel(project);
44.62 + }
44.63 +
44.64 + @Override
44.65 + public void addChangeListener(ChangeListener listener) {
44.66 + this.cs.addChangeListener(listener);
44.67 + }
44.68 +
44.69 + @Override
44.70 + public void removeChangeListener(ChangeListener listener) {
44.71 + this.cs.removeChangeListener(listener);
44.72 + }
44.73 +
44.74 + @Override
44.75 + public void propertyChange(PropertyChangeEvent evt) {
44.76 +// final String name = evt.getPropertyName();
44.77 +// if (name == null ||
44.78 +// PLATFORM_ACTIVE.equals(name)) {
44.79 + this.cs.fireChange();
44.80 +// }
44.81 + }
44.82 +
44.83 + @Override
44.84 + public String toString() {
44.85 + final String sl = getSourceLevel();
44.86 + return sl == null ? "" : sl; //NOI18M
44.87 + }
44.88 +
44.89 + }
44.90 +
44.91 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/PythonSources.java Tue Feb 24 01:58:36 2015 -0800
45.3 @@ -0,0 +1,45 @@
45.4 +/*
45.5 + * To change this license header, choose License Headers in Project Properties.
45.6 + * To change this template file, choose Tools | Templates
45.7 + * and open the template in the editor.
45.8 + */
45.9 +package org.netbeans.modules.python.project2;
45.10 +
45.11 +import javax.swing.event.ChangeListener;
45.12 +import org.netbeans.api.project.SourceGroup;
45.13 +import org.netbeans.api.project.Sources;
45.14 +import org.netbeans.spi.project.support.GenericSources;
45.15 +import org.openide.filesystems.FileObject;
45.16 +
45.17 +/**
45.18 + *
45.19 + * @author Ralph Benjamin Ruijs <ralphbenjamin@netbeans.org>
45.20 + */
45.21 +public class PythonSources implements Sources {
45.22 + private final PythonProject2 project;
45.23 + private SourceGroup[] roots;
45.24 +
45.25 +
45.26 + public PythonSources(PythonProject2 project) {
45.27 + this.project = project;
45.28 + }
45.29 +
45.30 + @Override
45.31 + public SourceGroup[] getSourceGroups(String type) {
45.32 + synchronized(this) {
45.33 + if(roots == null) {
45.34 + FileObject fo = project.getProjectDirectory();
45.35 + roots = new SourceGroup[]{GenericSources.group(project, fo, fo.getPath(), "Source Packages", null, null)};
45.36 + }
45.37 + }
45.38 + return roots;
45.39 + }
45.40 +
45.41 + @Override
45.42 + public void addChangeListener(ChangeListener listener) {
45.43 + }
45.44 +
45.45 + @Override
45.46 + public void removeChangeListener(ChangeListener listener) {
45.47 + }
45.48 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/classpath/BootClassPathImplementation.java Tue Feb 24 01:58:36 2015 -0800
46.3 @@ -0,0 +1,127 @@
46.4 +/*
46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
46.6 + *
46.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
46.8 + *
46.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
46.10 + * Other names may be trademarks of their respective owners.
46.11 + *
46.12 + * The contents of this file are subject to the terms of either the GNU
46.13 + * General Public License Version 2 only ("GPL") or the Common
46.14 + * Development and Distribution License("CDDL") (collectively, the
46.15 + * "License"). You may not use this file except in compliance with the
46.16 + * License. You can obtain a copy of the License at
46.17 + * http://www.netbeans.org/cddl-gplv2.html
46.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
46.19 + * specific language governing permissions and limitations under the
46.20 + * License. When distributing the software, include this License Header
46.21 + * Notice in each file and include the License file at
46.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
46.23 + * particular file as subject to the "Classpath" exception as provided
46.24 + * by Oracle in the GPL Version 2 section of the License file that
46.25 + * accompanied this code. If applicable, add the following below the
46.26 + * License Header, with the fields enclosed by brackets [] replaced by
46.27 + * your own identifying information:
46.28 + * "Portions Copyrighted [year] [name of copyright owner]"
46.29 + *
46.30 + * Contributor(s):
46.31 + *
46.32 + * The Original Software is NetBeans. The Initial Developer of the Original
46.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
46.34 + * Microsystems, Inc. All Rights Reserved.
46.35 + *
46.36 + * If you wish your version of this file to be governed by only the CDDL
46.37 + * or only the GPL Version 2, indicate your decision by adding
46.38 + * "[Contributor] elects to include this software in this distribution
46.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
46.40 + * single choice of license, a recipient has the option to distribute
46.41 + * your version of this file under either the CDDL, the GPL Version 2 or
46.42 + * to extend the choice of license to its licensees as provided above.
46.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
46.44 + * Version 2 license, then the option applies only if the new code is
46.45 + * made subject to such option by the copyright holder.
46.46 + */
46.47 +package org.netbeans.modules.python.project2.classpath;
46.48 +
46.49 +import java.beans.PropertyChangeEvent;
46.50 +import java.beans.PropertyChangeListener;
46.51 +import java.beans.PropertyChangeSupport;
46.52 +import java.net.URL;
46.53 +import java.util.List;
46.54 +import java.util.ArrayList;
46.55 +import java.util.Collections;
46.56 +import org.netbeans.modules.python.api.PythonPlatform;
46.57 +import org.netbeans.modules.python.api.PythonPlatformManager;
46.58 +import org.netbeans.modules.python.project2.PythonProject2;
46.59 +import org.netbeans.spi.java.classpath.ClassPathImplementation;
46.60 +import org.netbeans.spi.java.classpath.PathResourceImplementation;
46.61 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
46.62 +import org.openide.util.Parameters;
46.63 +
46.64 +final class BootClassPathImplementation implements ClassPathImplementation, PropertyChangeListener {
46.65 + private List<PathResourceImplementation> resourcesCache;
46.66 + private final PropertyChangeSupport support = new PropertyChangeSupport(this);
46.67 + private final PythonProject2 project;
46.68 +
46.69 + public BootClassPathImplementation (final PythonProject2 project) {
46.70 + assert project != null;
46.71 + this.project = project;
46.72 +// this.eval.addPropertyChangeListener(WeakListeners.propertyChange(this, this.eval));
46.73 + }
46.74 +
46.75 + @Override
46.76 + public synchronized List<PathResourceImplementation> getResources() {
46.77 + if (this.resourcesCache == null) {
46.78 + List<URL> urls = getUrls(project);
46.79 + List<PathResourceImplementation> result = new ArrayList<>(1);
46.80 + for (URL url : urls) {
46.81 + result.add(ClassPathSupport.createResource(url));
46.82 + }
46.83 + resourcesCache = Collections.unmodifiableList(result);
46.84 + }
46.85 + return this.resourcesCache;
46.86 + }
46.87 +
46.88 + @Override
46.89 + public void addPropertyChangeListener(PropertyChangeListener listener) {
46.90 + Parameters.notNull("listener", listener);
46.91 + this.support.addPropertyChangeListener (listener);
46.92 + }
46.93 +
46.94 + @Override
46.95 + public void removePropertyChangeListener(PropertyChangeListener listener) {
46.96 + Parameters.notNull("listener", listener);
46.97 + this.support.removePropertyChangeListener (listener);
46.98 + }
46.99 +
46.100 + @Override
46.101 + public void propertyChange(final PropertyChangeEvent evt) {
46.102 +// if (evt.getSource() == this.eval &&
46.103 +// (evt.getPropertyName() == null || evt.getPropertyName().equals(PythonProjectProperties.ACTIVE_PLATFORM))) {
46.104 +// //Active platform was changed
46.105 +// RequestProcessor.getDefault().post(new Runnable() {
46.106 +// @Override
46.107 +// public void run() {
46.108 +// resetCache ();
46.109 +// }
46.110 +// }) ;
46.111 +// }
46.112 + }
46.113 +
46.114 + private void resetCache () {
46.115 + synchronized (this) {
46.116 + resourcesCache = null;
46.117 + }
46.118 + support.firePropertyChange(PROP_RESOURCES, null, null);
46.119 + }
46.120 +
46.121 + private List<URL> getUrls(PythonProject2 project) {
46.122 + PythonPlatform activePlatform = project.getActivePlatform();
46.123 + if (activePlatform == null) {
46.124 + final PythonPlatformManager manager = PythonPlatformManager.getInstance();
46.125 + final String platformName = manager.getDefaultPlatform();
46.126 + activePlatform = manager.getPlatform(platformName);
46.127 + }
46.128 + return activePlatform.getUrls();
46.129 + }
46.130 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/classpath/ClassPathProviderImpl.java Tue Feb 24 01:58:36 2015 -0800
47.3 @@ -0,0 +1,205 @@
47.4 +/*
47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
47.6 + *
47.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
47.8 + *
47.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
47.10 + * Other names may be trademarks of their respective owners.
47.11 + *
47.12 + * The contents of this file are subject to the terms of either the GNU
47.13 + * General Public License Version 2 only ("GPL") or the Common
47.14 + * Development and Distribution License("CDDL") (collectively, the
47.15 + * "License"). You may not use this file except in compliance with the
47.16 + * License. You can obtain a copy of the License at
47.17 + * http://www.netbeans.org/cddl-gplv2.html
47.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
47.19 + * specific language governing permissions and limitations under the
47.20 + * License. When distributing the software, include this License Header
47.21 + * Notice in each file and include the License file at
47.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
47.23 + * particular file as subject to the "Classpath" exception as provided
47.24 + * by Oracle in the GPL Version 2 section of the License file that
47.25 + * accompanied this code. If applicable, add the following below the
47.26 + * License Header, with the fields enclosed by brackets [] replaced by
47.27 + * your own identifying information:
47.28 + * "Portions Copyrighted [year] [name of copyright owner]"
47.29 + *
47.30 + * Contributor(s):
47.31 + *
47.32 + * The Original Software is NetBeans. The Initial Developer of the Original
47.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
47.34 + * Microsystems, Inc. All Rights Reserved.
47.35 + *
47.36 + * If you wish your version of this file to be governed by only the CDDL
47.37 + * or only the GPL Version 2, indicate your decision by adding
47.38 + * "[Contributor] elects to include this software in this distribution
47.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
47.40 + * single choice of license, a recipient has the option to distribute
47.41 + * your version of this file under either the CDDL, the GPL Version 2 or
47.42 + * to extend the choice of license to its licensees as provided above.
47.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
47.44 + * Version 2 license, then the option applies only if the new code is
47.45 + * made subject to such option by the copyright holder.
47.46 + */
47.47 +package org.netbeans.modules.python.project2.classpath;
47.48 +
47.49 +import java.util.HashMap;
47.50 +import java.util.Map;
47.51 +import org.netbeans.api.java.classpath.ClassPath;
47.52 +import org.netbeans.api.project.ProjectUtils;
47.53 +import org.netbeans.api.project.SourceGroup;
47.54 +import org.netbeans.api.project.Sources;
47.55 +import org.netbeans.modules.python.project2.PythonProject2;
47.56 +import org.netbeans.spi.java.classpath.ClassPathFactory;
47.57 +import org.netbeans.spi.java.classpath.ClassPathImplementation;
47.58 +import org.netbeans.spi.java.classpath.ClassPathProvider;
47.59 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
47.60 +import org.openide.filesystems.FileObject;
47.61 +import org.openide.filesystems.FileUtil;
47.62 +import org.openide.util.Pair;
47.63 +
47.64 +/**
47.65 + * Defines various paths for the Python Project.
47.66 + * Based on the Ruby project, in turn based on the J2SE project.
47.67 + * Greatly simplified at the moment since Python projects don't have a Sources object,
47.68 + * and there's no separate source/test folders.
47.69 + * @author Tor Norbye
47.70 + * @author Tomas Zezula
47.71 + */
47.72 +public final class ClassPathProviderImpl implements ClassPathProvider {
47.73 + private final PythonProject2 project;
47.74 + private final Sources sources;
47.75 + private final Map<Pair<String,Integer>,ClassPath> cache = new HashMap<>();
47.76 +
47.77 + public ClassPathProviderImpl(final PythonProject2 project, Sources sources) {
47.78 + assert project != null;
47.79 + this.project = project;
47.80 + this.sources = sources;
47.81 + assert this.sources != null;
47.82 + }
47.83 +
47.84 + private static final int MAX_TYPES = 3;
47.85 + /**
47.86 + * Find what a given file represents.
47.87 + * @param file a file in the project
47.88 + * @return one of: <dl>
47.89 + * <dt>0</dt> <dd>normal source</dd>
47.90 + * <dt>1</dt> <dd>test source</dd>
47.91 + * <dt>2</dt> <dd>the project root</dd>
47.92 + * <dt>-1</dt> <dd>something else</dd>
47.93 + * </dl>
47.94 + */
47.95 + private int getType(FileObject file) {
47.96 + if (file == project.getProjectDirectory()) {
47.97 + return 2;
47.98 + }
47.99 + for (SourceGroup sourceGroup : sources.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON)) {
47.100 + FileObject root = sourceGroup.getRootFolder();
47.101 + if (root.equals(file) || FileUtil.isParentOf(root, file)) {
47.102 + return 0;
47.103 + }
47.104 + }
47.105 + return -1;
47.106 + }
47.107 +
47.108 + private synchronized ClassPath getSourcepath(FileObject file) {
47.109 + int type = getType(file);
47.110 + return this.getSourcepath(type);
47.111 + }
47.112 +
47.113 + private ClassPath getSourcepath(int type) {
47.114 + if (type < 0 || type > MAX_TYPES) {
47.115 + return null;
47.116 + }
47.117 + final Pair<String,Integer> key = Pair.of(ClassPath.SOURCE, type);
47.118 + ClassPath cp = cache.get(key);
47.119 + if (cp == null) {
47.120 + switch (type) {
47.121 + case 0:
47.122 + cp = ClassPathFactory.createClassPath(new SourcePathImplementation(sources));
47.123 + break;
47.124 +// case 1:
47.125 +// cp = ClassPathFactory.createClassPath(new SourcePathImplementation(tests));
47.126 +// break;
47.127 + case 2:
47.128 + // Classpath for the "whole project" - for now just use the sources
47.129 + // Used from the tasklist for example.
47.130 + cp = ClassPathFactory.createClassPath(new SourcePathImplementation(sources));
47.131 + break;
47.132 +
47.133 + default:
47.134 + throw new UnsupportedOperationException("Only sources are available in the Python project at this point");
47.135 + }
47.136 + cache.put (key,cp);
47.137 + }
47.138 + return cp;
47.139 + }
47.140 +
47.141 + private synchronized ClassPath getBootClassPath() {
47.142 + final Pair<String,Integer> key = Pair.of(ClassPath.BOOT, 0);
47.143 + ClassPath cp = cache.get(key);
47.144 + if (cp == null) {
47.145 + //todo: For now merge compile and platform class paths
47.146 + //under parsing api they should be separated
47.147 + final ClassPathImplementation boot = new BootClassPathImplementation(project);
47.148 + final ClassPathImplementation compile = new CompilePathImplementation(project);
47.149 + cp = ClassPathFactory.createClassPath(ClassPathSupport.createProxyClassPathImplementation(boot,compile));
47.150 + cache.put (key,cp);
47.151 + }
47.152 + return cp;
47.153 + }
47.154 +
47.155 +// private synchronized ClassPath getCompileClassPath() {
47.156 +// final Pair<String,Integer> key = Pair.of(ClassPath.COMPILE, 0);
47.157 +// ClassPath cp = cache.get(key);
47.158 +// if (cp == null) {
47.159 +// cp = ClassPathFactory.createClassPath(new CompilePathImplementation(this.project));
47.160 +// cache.put (key,cp);
47.161 +// }
47.162 +// return cp;
47.163 +// }
47.164 +
47.165 + @Override
47.166 + public ClassPath findClassPath(FileObject file, String type) {
47.167 + if (type.equals(ClassPath.SOURCE)) {
47.168 + return getSourcepath(file);
47.169 + } else if (type.equals(ClassPath.BOOT)) {
47.170 + return getBootClassPath();
47.171 + } else if (type.equals(ClassPath.COMPILE)) {
47.172 + // Bogus
47.173 + return getBootClassPath();
47.174 + } else {
47.175 + return null;
47.176 + }
47.177 + }
47.178 +
47.179 + /**
47.180 + * Returns array of all classpaths of the given type in the project.
47.181 + * The result is used for example for GlobalPathRegistry registrations.
47.182 + */
47.183 + public ClassPath[] getProjectClassPaths(String type) {
47.184 + if (ClassPath.BOOT.equals(type)) {
47.185 + return new ClassPath[]{getBootClassPath()};
47.186 + }
47.187 + if (ClassPath.SOURCE.equals(type)) {
47.188 + ClassPath[] l = new ClassPath[1];
47.189 + l[0] = getSourcepath(0);
47.190 + return l;
47.191 + }
47.192 + return null;
47.193 + }
47.194 +
47.195 + /**
47.196 + * Returns the given type of the classpath for the project sources
47.197 + * (i.e., excluding tests roots). Valid types are BOOT, SOURCE and COMPILE.
47.198 + */
47.199 + public ClassPath getProjectSourcesClassPath(String type) {
47.200 + if (ClassPath.BOOT.equals(type)) {
47.201 + return getBootClassPath();
47.202 + }
47.203 + if (ClassPath.SOURCE.equals(type)) {
47.204 + return getSourcepath(0);
47.205 + }
47.206 + return null;
47.207 + }
47.208 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/classpath/CompilePathImplementation.java Tue Feb 24 01:58:36 2015 -0800
48.3 @@ -0,0 +1,147 @@
48.4 +/*
48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
48.6 + *
48.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
48.8 + *
48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
48.10 + * Other names may be trademarks of their respective owners.
48.11 + *
48.12 + * The contents of this file are subject to the terms of either the GNU
48.13 + * General Public License Version 2 only ("GPL") or the Common
48.14 + * Development and Distribution License("CDDL") (collectively, the
48.15 + * "License"). You may not use this file except in compliance with the
48.16 + * License. You can obtain a copy of the License at
48.17 + * http://www.netbeans.org/cddl-gplv2.html
48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
48.19 + * specific language governing permissions and limitations under the
48.20 + * License. When distributing the software, include this License Header
48.21 + * Notice in each file and include the License file at
48.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
48.23 + * particular file as subject to the "Classpath" exception as provided
48.24 + * by Oracle in the GPL Version 2 section of the License file that
48.25 + * accompanied this code. If applicable, add the following below the
48.26 + * License Header, with the fields enclosed by brackets [] replaced by
48.27 + * your own identifying information:
48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
48.29 + *
48.30 + * If you wish your version of this file to be governed by only the CDDL
48.31 + * or only the GPL Version 2, indicate your decision by adding
48.32 + * "[Contributor] elects to include this software in this distribution
48.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
48.34 + * single choice of license, a recipient has the option to distribute
48.35 + * your version of this file under either the CDDL, the GPL Version 2 or
48.36 + * to extend the choice of license to its licensees as provided above.
48.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
48.38 + * Version 2 license, then the option applies only if the new code is
48.39 + * made subject to such option by the copyright holder.
48.40 + *
48.41 + * Contributor(s):
48.42 + *
48.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
48.44 + */
48.45 +package org.netbeans.modules.python.project2.classpath;
48.46 +
48.47 +import java.beans.PropertyChangeEvent;
48.48 +import java.beans.PropertyChangeListener;
48.49 +import java.beans.PropertyChangeSupport;
48.50 +import java.io.File;
48.51 +import java.util.ArrayList;
48.52 +import java.util.Collections;
48.53 +import java.util.List;
48.54 +import java.util.concurrent.atomic.AtomicBoolean;
48.55 +import org.netbeans.api.project.ProjectManager;
48.56 +import org.netbeans.modules.python.project2.PythonProject2;
48.57 +import org.netbeans.spi.java.classpath.ClassPathImplementation;
48.58 +import org.netbeans.spi.java.classpath.PathResourceImplementation;
48.59 +import org.openide.filesystems.FileObject;
48.60 +import org.openide.filesystems.FileUtil;
48.61 +import org.openide.util.Parameters;
48.62 +
48.63 +/**
48.64 + *
48.65 + * @author Tomas Zezula
48.66 + */
48.67 +public final class CompilePathImplementation implements ClassPathImplementation, PropertyChangeListener, Runnable {
48.68 +
48.69 + private final PropertyChangeSupport support = new PropertyChangeSupport(this);
48.70 + private final File projectFolder;
48.71 + private List<PathResourceImplementation> resources;
48.72 + private AtomicBoolean dirty = new AtomicBoolean();
48.73 +
48.74 + CompilePathImplementation(final PythonProject2 project) {
48.75 + assert project != null;
48.76 + FileObject fo = project.getProjectDirectory();;
48.77 + assert fo != null;
48.78 + this.projectFolder = FileUtil.toFile(fo);
48.79 + assert projectFolder != null;
48.80 + this.resources = this.getPath();
48.81 + }
48.82 +
48.83 + @Override
48.84 + public synchronized List<PathResourceImplementation> getResources() {
48.85 + assert this.resources != null;
48.86 + return this.resources;
48.87 + }
48.88 +
48.89 + @Override
48.90 + public void addPropertyChangeListener(final PropertyChangeListener listener) {
48.91 + Parameters.notNull("listener", listener);
48.92 + support.addPropertyChangeListener(listener);
48.93 + }
48.94 +
48.95 + @Override
48.96 + public void removePropertyChangeListener(PropertyChangeListener listener) {
48.97 + Parameters.notNull("listener", listener);
48.98 + support.removePropertyChangeListener(listener);
48.99 + }
48.100 +
48.101 + @Override
48.102 + public void propertyChange(final PropertyChangeEvent evt) {
48.103 + String prop = evt.getPropertyName();
48.104 +// if (prop != null && !PythonProjectProperties.PYTHON_LIB_PATH.equals(evt.getPropertyName())) {
48.105 +// // Not interesting to us.
48.106 +// return;
48.107 +// }
48.108 + // Coalesce changes; can come in fast after huge CP changes (#47910):
48.109 + if (!dirty.getAndSet(true)) {
48.110 + ProjectManager.mutex().postReadRequest(this);
48.111 + }
48.112 + }
48.113 +
48.114 + @Override
48.115 + public void run() {
48.116 + dirty.set(false);
48.117 + List<PathResourceImplementation> newRoots = getPath();
48.118 + boolean fire = false;
48.119 + synchronized (this) {
48.120 + if (!this.resources.equals(newRoots)) {
48.121 + this.resources = newRoots;
48.122 + fire = true;
48.123 + }
48.124 + }
48.125 + if (fire) {
48.126 + support.firePropertyChange(PROP_RESOURCES, null, null);
48.127 + }
48.128 + }
48.129 +
48.130 + private List<PathResourceImplementation> getPath() {
48.131 + List<PathResourceImplementation> result = new ArrayList<>();
48.132 +
48.133 +// String prop = evaluator.getProperty(PythonProjectProperties.PYTHON_LIB_PATH);
48.134 +// if (prop != null) {
48.135 +// //todo: Use PropertyUtil
48.136 +// final StringTokenizer tokenizer = new StringTokenizer(prop, "|"); //NOI18N
48.137 +// while (tokenizer.hasMoreTokens()) {
48.138 +// String piece = tokenizer.nextToken();
48.139 +// File f = PropertyUtils.resolveFile(this.projectFolder, piece);
48.140 +// URL entry = FileUtil.urlForArchiveOrDir(f);
48.141 +// if (entry != null) {
48.142 +// result.add(ClassPathSupport.createResource(entry));
48.143 +// } else {
48.144 +// Logger.getLogger(CompilePathImplementation.class.getName()).warning(f + " does not look like a valid archive file");
48.145 +// }
48.146 +// }
48.147 +// }
48.148 + return Collections.unmodifiableList(result);
48.149 + }
48.150 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/classpath/SourcePathImplementation.java Tue Feb 24 01:58:36 2015 -0800
49.3 @@ -0,0 +1,109 @@
49.4 +/*
49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
49.6 + *
49.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
49.8 + *
49.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
49.10 + * Other names may be trademarks of their respective owners.
49.11 + *
49.12 + * The contents of this file are subject to the terms of either the GNU
49.13 + * General Public License Version 2 only ("GPL") or the Common
49.14 + * Development and Distribution License("CDDL") (collectively, the
49.15 + * "License"). You may not use this file except in compliance with the
49.16 + * License. You can obtain a copy of the License at
49.17 + * http://www.netbeans.org/cddl-gplv2.html
49.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
49.19 + * specific language governing permissions and limitations under the
49.20 + * License. When distributing the software, include this License Header
49.21 + * Notice in each file and include the License file at
49.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
49.23 + * particular file as subject to the "Classpath" exception as provided
49.24 + * by Oracle in the GPL Version 2 section of the License file that
49.25 + * accompanied this code. If applicable, add the following below the
49.26 + * License Header, with the fields enclosed by brackets [] replaced by
49.27 + * your own identifying information:
49.28 + * "Portions Copyrighted [year] [name of copyright owner]"
49.29 + *
49.30 + * Contributor(s):
49.31 + *
49.32 + * The Original Software is NetBeans. The Initial Developer of the Original
49.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
49.34 + * Microsystems, Inc. All Rights Reserved.
49.35 + *
49.36 + * If you wish your version of this file to be governed by only the CDDL
49.37 + * or only the GPL Version 2, indicate your decision by adding
49.38 + * "[Contributor] elects to include this software in this distribution
49.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
49.40 + * single choice of license, a recipient has the option to distribute
49.41 + * your version of this file under either the CDDL, the GPL Version 2 or
49.42 + * to extend the choice of license to its licensees as provided above.
49.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
49.44 + * Version 2 license, then the option applies only if the new code is
49.45 + * made subject to such option by the copyright holder.
49.46 + */
49.47 +package org.netbeans.modules.python.project2.classpath;
49.48 +
49.49 +import java.beans.PropertyChangeEvent;
49.50 +import java.util.List;
49.51 +import java.util.ArrayList;
49.52 +import java.util.Collections;
49.53 +import java.beans.PropertyChangeListener;
49.54 +import java.beans.PropertyChangeSupport;
49.55 +import org.netbeans.api.project.SourceGroup;
49.56 +import org.netbeans.api.project.Sources;
49.57 +import org.netbeans.modules.python.project2.PythonProject2;
49.58 +import org.netbeans.spi.java.classpath.ClassPathImplementation;
49.59 +import org.netbeans.spi.java.classpath.PathResourceImplementation;
49.60 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
49.61 +
49.62 +/**
49.63 + * Source class path implementation
49.64 + * @author Tor Norbye
49.65 + * @author Tomas Zezula
49.66 + */
49.67 +final class SourcePathImplementation implements ClassPathImplementation, PropertyChangeListener {
49.68 + private final PropertyChangeSupport support = new PropertyChangeSupport(this);
49.69 + private List<PathResourceImplementation> resources;
49.70 + private final Sources src;
49.71 +
49.72 + public SourcePathImplementation(Sources sources) {
49.73 + assert sources != null;
49.74 + this.src = sources;
49.75 +// this.src.addPropertyChangeListener(WeakListeners.propertyChange(this, this.src));
49.76 + }
49.77 +
49.78 + @Override
49.79 + public List<PathResourceImplementation> getResources() {
49.80 + synchronized (this) {
49.81 + if (this.resources != null) {
49.82 + return this.resources;
49.83 + }
49.84 + }
49.85 + final SourceGroup[] urls = this.src.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON);
49.86 + synchronized (this) {
49.87 + if (this.resources == null) {
49.88 + List<PathResourceImplementation> result = new ArrayList<>(urls.length);
49.89 + for (SourceGroup root : urls) {
49.90 + result.add(ClassPathSupport.createResource(root.getRootFolder().toURL()));
49.91 + }
49.92 + this.resources = Collections.unmodifiableList(result);
49.93 + }
49.94 + return this.resources;
49.95 + }
49.96 + }
49.97 +
49.98 + @Override
49.99 + public void addPropertyChangeListener(PropertyChangeListener listener) {
49.100 + support.addPropertyChangeListener (listener);
49.101 + }
49.102 +
49.103 + @Override
49.104 + public void removePropertyChangeListener(PropertyChangeListener listener) {
49.105 + support.removePropertyChangeListener (listener);
49.106 + }
49.107 +
49.108 + @Override
49.109 + public synchronized void propertyChange(PropertyChangeEvent evt) {
49.110 + this.resources = null;
49.111 + }
49.112 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/layer.xml Tue Feb 24 01:58:36 2015 -0800
50.3 @@ -0,0 +1,39 @@
50.4 +<?xml version="1.0" encoding="UTF-8"?>
50.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
50.6 +<filesystem>
50.7 + <folder name="Projects">
50.8 + <folder name="Actions"/>
50.9 +
50.10 + <folder name="org-netbeans-modules-python-project2">
50.11 + <folder name="Nodes">
50.12 + <file name="org-netbeans-modules-python-project2-ui-SourceNodeFactory.instance">
50.13 + <attr name="position" intvalue="200"/>
50.14 + </file>
50.15 + </folder>
50.16 +
50.17 + <folder name="Customizer">
50.18 + <file name="PythonPath.instance">
50.19 + <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.project2.ui.customizer.CompositePanelProviderImpl.createPythonPath"/>
50.20 + <attr name="position" intvalue="200"/>
50.21 + </file>
50.22 + <file name="Run.instance">
50.23 + <attr name="instanceCreate" methodvalue="org.netbeans.modules.python.project2.ui.customizer.CompositePanelProviderImpl.createRunConfig"/>
50.24 + <attr name="position" intvalue="300"/>
50.25 + </file>
50.26 + <file name="Formatting.instance">
50.27 + <attr name="instanceOf" stringvalue="org.netbeans.spi.project.ui.support.ProjectCustomizer$CompositeCategoryProvider"/>
50.28 + <attr name="instanceCreate" methodvalue="org.netbeans.modules.options.indentation.FormattingCustomizerPanel.createCategoryProvider"/>
50.29 + <attr name="allowedMimeTypes" stringvalue="text/x-python"/>
50.30 + <attr name="position" intvalue="1000"/>
50.31 + </file>
50.32 + </folder>
50.33 + </folder>
50.34 + </folder>
50.35 + <folder name="Templates">
50.36 + <folder name="Project">
50.37 + <folder name="Python">
50.38 + <attr name="position" intvalue="1412"/>
50.39 + </folder>
50.40 + </folder>
50.41 + </folder>
50.42 +</filesystem>
51.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/brokenProjectBadge.gif has changed
52.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/package.gif has changed
53.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/packageBadge.gif has changed
54.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/packageEmpty.gif has changed
55.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/packagePrivate.gif has changed
56.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/packagePublic.gif has changed
57.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/py_25_16.png has changed
58.1 Binary file python.project2/src/org/netbeans/modules/python/project2/resources/sourceBadge.gif has changed
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/Bundle.properties Tue Feb 24 01:58:36 2015 -0800
59.3 @@ -0,0 +1,57 @@
59.4 +# Python project wizards
59.5 +LBL_IteratorName={0} of {1}
59.6 +LBL_NewPythonProjectWizardIterator_WizardProgress_CreatingProject=Creating new project
59.7 +LBL_NewPythonProjectWizardIterator_WizardProgress_PreparingToOpen=Preparing new project to be opened
59.8 +TXT_PythonProject=Python Project
59.9 +TXT_ExistingPythonProject=Python Project with Existing Sources
59.10 +LBL_ProjectNameLocation=Name and Location
59.11 +LBL_ProjectSources=Existing Sources
59.12 +
59.13 +#PanelOptionsVisual
59.14 +TXT_MainFileName={0}.py
59.15 +ERROR_IllegalMainFileName=Illegal main file name.
59.16 +LBL_setAsMainCheckBox=Set as &Main Project
59.17 +ACSD_setAsMainCheckBox=N/A
59.18 +ACSN_setAsMainCheckBox=N/A
59.19 +ACSN_createMainCheckBox=Create Main Class
59.20 +ACSD_createMainCheckBox=Select checkbox to create main class in project.
59.21 +LBL_createMainCheckBox=&Create Main File
59.22 +ASCN_mainClassTextFiled=N/A
59.23 +ASCD_mainClassTextFiled=N/A
59.24 +ACSN_PanelOptionsVisual=N/A
59.25 +ACSD_PanelOptionsVisual=N/A
59.26 +
59.27 +#PanelConfigureProjectVisual
59.28 +TXT_NameAndLoc=Name and Location
59.29 +TXT_NewPythonApp=New Python Application
59.30 +ACSD_NewPythonApp=New Python Application
59.31 +ACSN_locationContainer=N/A
59.32 +ACSD_locationContainer=N/A
59.33 +ACSN_optionsContainer=N/A
59.34 +ACSD_optionsContainer=N/A
59.35 +TXT_PythonPlatform=&Python Platform:
59.36 +ERROR_IllegalPlatform=Wrong Python Platform
59.37 +TXT_ManagePlatfroms=&Manage...
59.38 +ACSD_ExistingPythonProject=N/A
59.39 +
59.40 +#PanelConfigureSourcesVisual
59.41 +LBL_SelectSources=Select Source Folder
59.42 +LBL_SelectTests=Select Test Folder
59.43 +
59.44 +ExistingPythonProjectPanelVisual.projectName.text=Project &Name:
59.45 +ExistingPythonProjectPanelVisual.projectFolder.text=Project &Folder:
59.46 +ExistingPythonProjectPanelVisual.browse.text=Br&owse
59.47 +LBL_SelectProjectFolder=Select project folder
59.48 +
59.49 +#Errors
59.50 +ERR_WrongName=Project Name is not a valid folder name.
59.51 +ERR_WrongProjectFolder=Project Folder is not a valid path.
59.52 +ERR_ReadOnlyProjectFolder=Project Folder cannot be created.
59.53 +ERR_AlreadyAnProject="There is already a NetBeans project in the project folder."
59.54 +PanelConfigureSourcesVisual.jLabel1.text=Specify the folders containing sources and tests.
59.55 +PanelConfigureSourcesVisual.jLabel2.text=&Source Root Folders
59.56 +PanelConfigureSourcesVisual.jLabel3.text=&Test Root Folders
59.57 +PanelConfigureSourcesVisual.addSource.text=&Add Folder...
59.58 +PanelConfigureSourcesVisual.removeSource.text=&Remove
59.59 +PanelConfigureSourcesVisual.addTest.text=Add F&older...
59.60 +PanelConfigureSourcesVisual.removeTest.text=Re&move
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/EmptyPythonProjectDescription.html Tue Feb 24 01:58:36 2015 -0800
60.3 @@ -0,0 +1,12 @@
60.4 +<!--
60.5 +To change this template, choose Tools | Templates
60.6 +and open the template in the editor.
60.7 +-->
60.8 +<html>
60.9 + <head>
60.10 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
60.11 + </head>
60.12 + <body>
60.13 + New Empty Python Project using setuptools
60.14 + </body>
60.15 +</html>
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/EmptyPythonProjectPanelVisual.form Tue Feb 24 01:58:36 2015 -0800
61.3 @@ -0,0 +1,112 @@
61.4 +<?xml version="1.0" encoding="UTF-8" ?>
61.5 +
61.6 +<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
61.7 + <AuxValues>
61.8 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
61.9 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
61.10 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
61.11 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
61.12 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
61.13 + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
61.14 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
61.15 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
61.16 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
61.17 + </AuxValues>
61.18 +
61.19 + <Layout>
61.20 + <DimensionLayout dim="0">
61.21 + <Group type="103" groupAlignment="0" attributes="0">
61.22 + <Group type="102" attributes="0">
61.23 + <Group type="103" groupAlignment="0" attributes="0">
61.24 + <Component id="projectLocationLabel" min="-2" max="-2" attributes="0"/>
61.25 + <Component id="createdFolderLabel" alignment="0" min="-2" max="-2" attributes="0"/>
61.26 + <Component id="projectNameLabel" min="-2" max="-2" attributes="0"/>
61.27 + </Group>
61.28 + <EmptySpace max="-2" attributes="0"/>
61.29 + <Group type="103" groupAlignment="0" attributes="0">
61.30 + <Group type="102" attributes="0">
61.31 + <Component id="projectLocationTextField" pref="238" max="32767" attributes="0"/>
61.32 + <EmptySpace max="-2" attributes="0"/>
61.33 + <Component id="browseButton" min="-2" max="-2" attributes="0"/>
61.34 + </Group>
61.35 + <Component id="projectNameTextField" pref="343" max="32767" attributes="0"/>
61.36 + <Component id="createdFolderTextField" alignment="0" pref="343" max="32767" attributes="0"/>
61.37 + </Group>
61.38 + </Group>
61.39 + </Group>
61.40 + </DimensionLayout>
61.41 + <DimensionLayout dim="1">
61.42 + <Group type="103" groupAlignment="0" attributes="0">
61.43 + <Group type="102" attributes="0">
61.44 + <EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
61.45 + <Group type="103" groupAlignment="3" attributes="0">
61.46 + <Component id="projectNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
61.47 + <Component id="projectNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
61.48 + </Group>
61.49 + <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
61.50 + <Group type="103" groupAlignment="3" attributes="0">
61.51 + <Component id="projectLocationLabel" alignment="3" min="-2" max="-2" attributes="0"/>
61.52 + <Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
61.53 + <Component id="projectLocationTextField" alignment="3" min="-2" max="-2" attributes="0"/>
61.54 + </Group>
61.55 + <EmptySpace max="-2" attributes="0"/>
61.56 + <Group type="103" groupAlignment="3" attributes="0">
61.57 + <Component id="createdFolderLabel" alignment="3" min="-2" max="-2" attributes="0"/>
61.58 + <Component id="createdFolderTextField" alignment="3" min="-2" max="-2" attributes="0"/>
61.59 + </Group>
61.60 + <EmptySpace pref="31" max="32767" attributes="0"/>
61.61 + </Group>
61.62 + </Group>
61.63 + </DimensionLayout>
61.64 + </Layout>
61.65 + <SubComponents>
61.66 + <Component class="javax.swing.JLabel" name="projectNameLabel">
61.67 + <Properties>
61.68 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
61.69 + <ComponentRef name="projectNameTextField"/>
61.70 + </Property>
61.71 + <Property name="text" type="java.lang.String" value="Project &Name:"/>
61.72 + </Properties>
61.73 + <AuxValues>
61.74 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
61.75 + </AuxValues>
61.76 + </Component>
61.77 + <Component class="javax.swing.JTextField" name="projectNameTextField">
61.78 + </Component>
61.79 + <Component class="javax.swing.JLabel" name="projectLocationLabel">
61.80 + <Properties>
61.81 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
61.82 + <ComponentRef name="projectLocationTextField"/>
61.83 + </Property>
61.84 + <Property name="text" type="java.lang.String" value="Project &Location:"/>
61.85 + </Properties>
61.86 + <AuxValues>
61.87 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
61.88 + </AuxValues>
61.89 + </Component>
61.90 + <Component class="javax.swing.JTextField" name="projectLocationTextField">
61.91 + </Component>
61.92 + <Component class="javax.swing.JButton" name="browseButton">
61.93 + <Properties>
61.94 + <Property name="text" type="java.lang.String" value="Br&owse..."/>
61.95 + <Property name="actionCommand" type="java.lang.String" value="BROWSE"/>
61.96 + </Properties>
61.97 + <Events>
61.98 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
61.99 + </Events>
61.100 + </Component>
61.101 + <Component class="javax.swing.JLabel" name="createdFolderLabel">
61.102 + <Properties>
61.103 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
61.104 + <ComponentRef name="createdFolderTextField"/>
61.105 + </Property>
61.106 + <Property name="text" type="java.lang.String" value="Project &Folder:"/>
61.107 + </Properties>
61.108 + </Component>
61.109 + <Component class="javax.swing.JTextField" name="createdFolderTextField">
61.110 + <Properties>
61.111 + <Property name="editable" type="boolean" value="false"/>
61.112 + </Properties>
61.113 + </Component>
61.114 + </SubComponents>
61.115 +</Form>
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/EmptyPythonProjectPanelVisual.java Tue Feb 24 01:58:36 2015 -0800
62.3 @@ -0,0 +1,264 @@
62.4 +/*
62.5 + * To change this template, choose Tools | Templates
62.6 + * and open the template in the editor.
62.7 + */
62.8 +
62.9 +package org.netbeans.modules.python.project2.templates;
62.10 +
62.11 +import java.io.File;
62.12 +import javax.swing.JFileChooser;
62.13 +import javax.swing.event.DocumentEvent;
62.14 +import javax.swing.event.DocumentListener;
62.15 +import javax.swing.text.Document;
62.16 +import org.netbeans.spi.project.ui.support.ProjectChooser;
62.17 +import org.openide.WizardDescriptor;
62.18 +import org.openide.WizardValidationException;
62.19 +import org.openide.filesystems.FileUtil;
62.20 +
62.21 +public final class EmptyPythonProjectPanelVisual extends SettingsPanel implements DocumentListener {
62.22 +
62.23 +
62.24 + private final PanelConfigureProject panel;
62.25 +
62.26 + public EmptyPythonProjectPanelVisual(PanelConfigureProject panel) {
62.27 + initComponents();
62.28 + this.panel = panel;
62.29 + // Register listener on the textFields to make the automatic updates
62.30 + projectNameTextField.getDocument().addDocumentListener(this);
62.31 + projectLocationTextField.getDocument().addDocumentListener(this);
62.32 + }
62.33 +
62.34 + public String getProjectName() {
62.35 + return this.projectNameTextField.getText();
62.36 + }
62.37 +
62.38 + /** This method is called from within the constructor to
62.39 + * initialize the form.
62.40 + * WARNING: Do NOT modify this code. The content of this method is
62.41 + * always regenerated by the Form Editor.
62.42 + */
62.43 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
62.44 + private void initComponents() {
62.45 +
62.46 + projectNameLabel = new javax.swing.JLabel();
62.47 + projectNameTextField = new javax.swing.JTextField();
62.48 + projectLocationLabel = new javax.swing.JLabel();
62.49 + projectLocationTextField = new javax.swing.JTextField();
62.50 + browseButton = new javax.swing.JButton();
62.51 + createdFolderLabel = new javax.swing.JLabel();
62.52 + createdFolderTextField = new javax.swing.JTextField();
62.53 +
62.54 + projectNameLabel.setLabelFor(projectNameTextField);
62.55 + org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel, "Project &Name:");
62.56 +
62.57 + projectLocationLabel.setLabelFor(projectLocationTextField);
62.58 + org.openide.awt.Mnemonics.setLocalizedText(projectLocationLabel, "Project &Location:");
62.59 +
62.60 + org.openide.awt.Mnemonics.setLocalizedText(browseButton, "Br&owse...");
62.61 + browseButton.setActionCommand("BROWSE");
62.62 + browseButton.addActionListener(new java.awt.event.ActionListener() {
62.63 + public void actionPerformed(java.awt.event.ActionEvent evt) {
62.64 + browseButtonActionPerformed(evt);
62.65 + }
62.66 + });
62.67 +
62.68 + createdFolderLabel.setLabelFor(createdFolderTextField);
62.69 + org.openide.awt.Mnemonics.setLocalizedText(createdFolderLabel, "Project &Folder:");
62.70 +
62.71 + createdFolderTextField.setEditable(false);
62.72 +
62.73 + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
62.74 + this.setLayout(layout);
62.75 + layout.setHorizontalGroup(
62.76 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
62.77 + .addGroup(layout.createSequentialGroup()
62.78 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
62.79 + .addComponent(projectLocationLabel)
62.80 + .addComponent(createdFolderLabel)
62.81 + .addComponent(projectNameLabel))
62.82 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
62.83 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
62.84 + .addGroup(layout.createSequentialGroup()
62.85 + .addComponent(projectLocationTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 238, Short.MAX_VALUE)
62.86 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
62.87 + .addComponent(browseButton))
62.88 + .addComponent(projectNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
62.89 + .addComponent(createdFolderTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)))
62.90 + );
62.91 + layout.setVerticalGroup(
62.92 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
62.93 + .addGroup(layout.createSequentialGroup()
62.94 + .addGap(20, 20, 20)
62.95 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
62.96 + .addComponent(projectNameLabel)
62.97 + .addComponent(projectNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
62.98 + .addGap(8, 8, 8)
62.99 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
62.100 + .addComponent(projectLocationLabel)
62.101 + .addComponent(browseButton)
62.102 + .addComponent(projectLocationTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
62.103 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
62.104 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
62.105 + .addComponent(createdFolderLabel)
62.106 + .addComponent(createdFolderTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
62.107 + .addContainerGap(31, Short.MAX_VALUE))
62.108 + );
62.109 + }// </editor-fold>//GEN-END:initComponents
62.110 +
62.111 + private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
62.112 + String command = evt.getActionCommand();
62.113 + if ("BROWSE".equals(command)) {
62.114 + JFileChooser chooser = new JFileChooser();
62.115 + chooser.setCurrentDirectory(null);
62.116 + chooser.setDialogTitle("Select Project Location");
62.117 + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
62.118 + String path = this.projectLocationTextField.getText();
62.119 + if (path.length() > 0) {
62.120 + File f = new File(path);
62.121 + if (f.exists()) {
62.122 + chooser.setSelectedFile(f);
62.123 + }
62.124 + }
62.125 + if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) {
62.126 + File projectDir = chooser.getSelectedFile();
62.127 + projectLocationTextField.setText(FileUtil.normalizeFile(projectDir).getAbsolutePath());
62.128 + }
62.129 + panel.fireChangeEvent();
62.130 + }
62.131 +
62.132 + }//GEN-LAST:event_browseButtonActionPerformed
62.133 + // Variables declaration - do not modify//GEN-BEGIN:variables
62.134 + private javax.swing.JButton browseButton;
62.135 + private javax.swing.JLabel createdFolderLabel;
62.136 + private javax.swing.JTextField createdFolderTextField;
62.137 + private javax.swing.JLabel projectLocationLabel;
62.138 + private javax.swing.JTextField projectLocationTextField;
62.139 + private javax.swing.JLabel projectNameLabel;
62.140 + private javax.swing.JTextField projectNameTextField;
62.141 + // End of variables declaration//GEN-END:variables
62.142 + @Override
62.143 + public void addNotify() {
62.144 + super.addNotify();
62.145 + //same problem as in 31086, initial focus on Cancel button
62.146 + projectNameTextField.requestFocus();
62.147 + }
62.148 +
62.149 + @Override
62.150 + boolean valid(WizardDescriptor wizardDescriptor) {
62.151 +
62.152 + if (projectNameTextField.getText().length() == 0) {
62.153 + wizardDescriptor.putProperty("WizardPanel_errorMessage",
62.154 + "Project Name is not a valid folder name.");
62.155 + return false; // Display name not specified
62.156 + }
62.157 + File f = FileUtil.normalizeFile(new File(projectLocationTextField.getText()).getAbsoluteFile());
62.158 + if (!f.isDirectory()) {
62.159 + String message = "Project Folder is not a valid path.";
62.160 + wizardDescriptor.putProperty("WizardPanel_errorMessage", message);
62.161 + return false;
62.162 + }
62.163 + final File destFolder = FileUtil.normalizeFile(new File(createdFolderTextField.getText()).getAbsoluteFile());
62.164 +
62.165 + File projLoc = destFolder;
62.166 + while (projLoc != null && !projLoc.exists()) {
62.167 + projLoc = projLoc.getParentFile();
62.168 + }
62.169 + if (projLoc == null || !projLoc.canWrite()) {
62.170 + wizardDescriptor.putProperty("WizardPanel_errorMessage",
62.171 + "Project Folder cannot be created.");
62.172 + return false;
62.173 + }
62.174 +
62.175 + if (FileUtil.toFileObject(projLoc) == null) {
62.176 + String message = "Project Folder is not a valid path.";
62.177 + wizardDescriptor.putProperty("WizardPanel_errorMessage", message);
62.178 + return false;
62.179 + }
62.180 +
62.181 + File[] kids = destFolder.listFiles();
62.182 + if (destFolder.exists() && kids != null && kids.length > 0) {
62.183 + // Folder exists and is not empty
62.184 + wizardDescriptor.putProperty("WizardPanel_errorMessage",
62.185 + "Project Folder already exists and is not empty.");
62.186 + return false;
62.187 + }
62.188 + wizardDescriptor.putProperty("WizardPanel_errorMessage", "");
62.189 + return true;
62.190 + }
62.191 +
62.192 + @Override
62.193 + void store(WizardDescriptor d) {
62.194 + String name = projectNameTextField.getText().trim();
62.195 + String folder = createdFolderTextField.getText().trim();
62.196 +
62.197 + d.putProperty(NewPythonProjectWizardIterator.PROP_PROJECT_LOCATION, new File(folder));
62.198 + d.putProperty(NewPythonProjectWizardIterator.PROP_PROJECT_NAME, name);
62.199 + }
62.200 +
62.201 + @Override
62.202 + void read(WizardDescriptor settings) {
62.203 + File projectLocation = (File) settings.getProperty(NewPythonProjectWizardIterator.PROP_PROJECT_LOCATION);
62.204 + if (projectLocation == null || projectLocation.getParentFile() == null || !projectLocation.getParentFile().isDirectory()) {
62.205 + projectLocation = ProjectChooser.getProjectsFolder();
62.206 + } else {
62.207 + projectLocation = projectLocation.getParentFile();
62.208 + }
62.209 + this.projectLocationTextField.setText(projectLocation.getAbsolutePath());
62.210 +
62.211 + String projectName = (String) settings.getProperty(NewPythonProjectWizardIterator.PROP_PROJECT_NAME);
62.212 + if (projectName == null) {
62.213 + projectName = NewPythonProjectWizardIterator.getFreeFolderName(projectLocation,"NewPythonProject"); //NOI18N
62.214 + }
62.215 + this.projectNameTextField.setText(projectName);
62.216 + this.projectNameTextField.selectAll();
62.217 + }
62.218 +
62.219 + @Override
62.220 + void validate(WizardDescriptor d) throws WizardValidationException {
62.221 + // nothing to validate
62.222 + }
62.223 +
62.224 + // Implementation of DocumentListener --------------------------------------
62.225 + @Override
62.226 + public void changedUpdate(DocumentEvent e) {
62.227 + updateTexts(e);
62.228 + if (this.projectNameTextField.getDocument() == e.getDocument()) {
62.229 + firePropertyChange(NewPythonProjectWizardIterator.PROP_PROJECT_NAME, null, this.projectNameTextField.getText());
62.230 + }
62.231 + }
62.232 +
62.233 + @Override
62.234 + public void insertUpdate(DocumentEvent e) {
62.235 + updateTexts(e);
62.236 + if (this.projectNameTextField.getDocument() == e.getDocument()) {
62.237 + firePropertyChange(NewPythonProjectWizardIterator.PROP_PROJECT_NAME, null, this.projectNameTextField.getText());
62.238 + }
62.239 + }
62.240 +
62.241 + @Override
62.242 + public void removeUpdate(DocumentEvent e) {
62.243 + updateTexts(e);
62.244 + if (this.projectNameTextField.getDocument() == e.getDocument()) {
62.245 + firePropertyChange(NewPythonProjectWizardIterator.PROP_PROJECT_NAME, null, this.projectNameTextField.getText());
62.246 + }
62.247 + }
62.248 +
62.249 + /** Handles changes in the Project name and project directory, */
62.250 + private void updateTexts(DocumentEvent e) {
62.251 +
62.252 + Document doc = e.getDocument();
62.253 +
62.254 + if (doc == projectNameTextField.getDocument() || doc == projectLocationTextField.getDocument()) {
62.255 + // Change in the project name
62.256 +
62.257 + String projectName = projectNameTextField.getText();
62.258 + String projectFolder = projectLocationTextField.getText();
62.259 +
62.260 + //if (projectFolder.trim().length() == 0 || projectFolder.equals(oldName)) {
62.261 + createdFolderTextField.setText(projectFolder + File.separatorChar + projectName);
62.262 + //}
62.263 +
62.264 + }
62.265 + panel.fireChangeEvent(); // Notify that the panel changed
62.266 + }
62.267 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/NewPythonProjectWizardIterator.java Tue Feb 24 01:58:36 2015 -0800
63.3 @@ -0,0 +1,273 @@
63.4 +package org.netbeans.modules.python.project2.templates;
63.5 +
63.6 +import java.io.File;
63.7 +import java.io.IOException;
63.8 +import java.util.HashMap;
63.9 +import java.util.HashSet;
63.10 +import java.util.Map;
63.11 +import java.util.NoSuchElementException;
63.12 +import java.util.Set;
63.13 +import javax.swing.event.ChangeListener;
63.14 +import org.netbeans.api.progress.ProgressHandle;
63.15 +import org.netbeans.api.project.Project;
63.16 +import org.netbeans.api.project.ProjectManager;
63.17 +import org.netbeans.api.templates.TemplateRegistration;
63.18 +import org.netbeans.modules.python.api.PythonPlatform;
63.19 +import org.netbeans.modules.python.api.PythonPlatformManager;
63.20 +import org.netbeans.modules.python.project2.PythonProject2;
63.21 +import org.netbeans.spi.project.ui.support.ProjectChooser;
63.22 +import org.openide.WizardDescriptor;
63.23 +import org.openide.filesystems.FileObject;
63.24 +import org.openide.filesystems.FileUtil;
63.25 +import org.openide.loaders.DataFolder;
63.26 +import org.openide.loaders.DataObject;
63.27 +import org.openide.util.Exceptions;
63.28 +import org.openide.util.Mutex;
63.29 +import org.openide.util.MutexException;
63.30 +import org.openide.util.NbBundle;
63.31 +
63.32 +public class NewPythonProjectWizardIterator implements WizardDescriptor.ProgressInstantiatingIterator {
63.33 +
63.34 + static final String PROP_MAIN_FILE = "mainFile"; //NOI18N
63.35 + static final String PROP_PROJECT_NAME = "projectName"; //NOI18N
63.36 + static final String PROP_PROJECT_LOCATION = "pojectLocation"; //NOI18N
63.37 + static final String PROP_PLATFORM_ID = "platform"; //NOI18N
63.38 +
63.39 + public static enum WizardType {
63.40 + APP
63.41 + }
63.42 +
63.43 + private final WizardType wizardType;
63.44 + private WizardDescriptor descriptor;
63.45 + private WizardDescriptor.Panel[] panels;
63.46 + private int index;
63.47 +
63.48 + public NewPythonProjectWizardIterator() {
63.49 + this(WizardType.APP);
63.50 + }
63.51 +
63.52 + private NewPythonProjectWizardIterator(WizardType wizardType) {
63.53 + this.wizardType = wizardType;
63.54 + }
63.55 +
63.56 + @TemplateRegistration(folder = "Project/Python", position = 152, displayName = "org.netbeans.modules.python.project2.Bundle#Templates/Project/Python/PythonProject2.xml", iconBase = "org/netbeans/modules/python/project2/resources/py_25_16.png", description = "/org/netbeans/modules/python/project2/templates/EmptyPythonProjectDescription.html")
63.57 + public static NewPythonProjectWizardIterator createApplication() {
63.58 + return new NewPythonProjectWizardIterator();
63.59 + }
63.60 +
63.61 + @Override
63.62 + public void initialize(WizardDescriptor wizard) {
63.63 + descriptor = wizard;
63.64 + index = 0;
63.65 + panels = createPanels();
63.66 + // normally we would do it in uninitialize but we have listener on ide options (=> NPE)
63.67 + initDescriptor(wizard);
63.68 + }
63.69 +
63.70 + @Override
63.71 + public void uninitialize(WizardDescriptor wizard) {
63.72 + panels = null;
63.73 + descriptor = null;
63.74 + }
63.75 +
63.76 + @Override
63.77 + public Set instantiate() throws IOException {
63.78 + assert false : "Cannot call this method if implements WizardDescriptor.ProgressInstantiatingIterator.";
63.79 + return null;
63.80 + }
63.81 +
63.82 + @Override
63.83 + public Set instantiate(ProgressHandle handle) throws IOException {
63.84 + final Set<FileObject> resultSet = new HashSet<>();
63.85 +
63.86 + handle.start(5);
63.87 +
63.88 + String msg = NbBundle.getMessage(
63.89 + NewPythonProjectWizardIterator.class, "LBL_NewPythonProjectWizardIterator_WizardProgress_CreatingProject");
63.90 + handle.progress(msg, 3);
63.91 + try {
63.92 + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
63.93 +
63.94 + @Override
63.95 + public Void run() throws MutexException {
63.96 + try {
63.97 + // project
63.98 + File projectDirectory = (File) descriptor.getProperty(PROP_PROJECT_LOCATION);
63.99 + ProjectChooser.setProjectsFolder(projectDirectory.getParentFile());
63.100 +
63.101 + final FileObject projectFO = FileUtil.createFolder(projectDirectory);
63.102 + String projectName = (String) descriptor.getProperty(PROP_PROJECT_NAME);
63.103 +
63.104 + Map<String, Object> params = new HashMap<>(2);
63.105 + /* org/netbeans/modules/python/editor/templates/setup.py
63.106 + * __author__="${user}"
63.107 + * __date__ ="$${date} ${time}$"
63.108 + *
63.109 + * from setuptools import setup,find_packages
63.110 + *
63.111 + * setup (
63.112 + * name = '${project_name}',
63.113 + * version = '0.1',
63.114 + * packages = find_packages(),
63.115 + *
63.116 + * # Declare your packages' dependencies here, for eg:
63.117 + * install_requires=[],
63.118 + *
63.119 + * # Fill in these to make your Egg ready for upload to
63.120 + * # PyPI
63.121 + * author = '${user}',
63.122 + * author_email = '',
63.123 + *
63.124 + * summary = 'Just another Python package for the cheese shop',
63.125 + * url = '',
63.126 + * license = '',
63.127 + * long_description= 'Long description of the package',
63.128 + *
63.129 + * # could also include long_description, download_url, classifiers, etc.
63.130 + * )
63.131 + */
63.132 + params.put("project_name", projectName); // NOI18N
63.133 + params.put("python3style", Boolean.TRUE);
63.134 + DataObject setuppy = createFromTemplate(FileUtil.getConfigFile("Templates/Python/_setup.py"), projectFO, "setup.py", params); // NOI18N
63.135 + // Do we want to open the setup.py?
63.136 +// resultSet.add(setuppy.getPrimaryFile());
63.137 + resultSet.add(projectFO);
63.138 +
63.139 + if (wizardType == WizardType.APP) {
63.140 + // package
63.141 + final String packageName = projectFO.getName().toLowerCase();
63.142 + FileObject packageFO = projectFO.createFolder(packageName);
63.143 + createFromTemplate(FileUtil.getConfigFile("Templates/Python/_init.py"), packageFO, "__init__.py", null); //NOI18N
63.144 + ProjectManager.getDefault().clearNonProjectCache();
63.145 + Project project = ProjectManager.getDefault().findProject(projectFO);
63.146 + // TODO: Change with provider in lookup cast is known to break
63.147 + PythonProject2 pyProj = (PythonProject2) project;
63.148 + final String platformId = (String) descriptor.getProperty(NewPythonProjectWizardIterator.PROP_PLATFORM_ID);
63.149 + PythonPlatform platform = PythonPlatformManager.getInstance().getPlatform(platformId);
63.150 + if(platform != null) {
63.151 + pyProj.setActivePlatform(platform);
63.152 + }
63.153 + // main file
63.154 + final String mainName = (String) descriptor.getProperty(NewPythonProjectWizardIterator.PROP_MAIN_FILE);
63.155 + if (mainName != null) {
63.156 + final FileObject mainFile = createFromTemplate(FileUtil.getConfigFile("Templates/Python/_module.py"), //NOI18N
63.157 + packageFO, mainName, params).getPrimaryFile();
63.158 + resultSet.add(mainFile);
63.159 + pyProj.setMainModule(FileUtil.getRelativePath(projectFO, mainFile));
63.160 + }
63.161 + ProjectManager.getDefault().saveProject(project);
63.162 + }
63.163 + } catch (IOException ex) {
63.164 + throw new MutexException(ex);
63.165 + }
63.166 + return null;
63.167 + }
63.168 + });
63.169 + } catch (MutexException ex) {
63.170 + Exceptions.printStackTrace(ex);
63.171 + }
63.172 +
63.173 + msg = NbBundle.getMessage(NewPythonProjectWizardIterator.class, "LBL_NewPythonProjectWizardIterator_WizardProgress_PreparingToOpen");
63.174 + handle.progress(msg, 5);
63.175 + return resultSet;
63.176 + }
63.177 +
63.178 + @Override
63.179 + public String name() {
63.180 + return NbBundle.getMessage(NewPythonProjectWizardIterator.class, "LBL_IteratorName", index + 1, panels.length);
63.181 + }
63.182 +
63.183 + @Override
63.184 + public boolean hasNext() {
63.185 + return index < panels.length - 1;
63.186 + }
63.187 +
63.188 + @Override
63.189 + public boolean hasPrevious() {
63.190 + return index > 0;
63.191 + }
63.192 +
63.193 + @Override
63.194 + public void nextPanel() {
63.195 + if (!hasNext()) {
63.196 + throw new NoSuchElementException();
63.197 + }
63.198 + index++;
63.199 + }
63.200 +
63.201 + @Override
63.202 + public void previousPanel() {
63.203 + if (!hasPrevious()) {
63.204 + throw new NoSuchElementException();
63.205 + }
63.206 + index--;
63.207 + }
63.208 +
63.209 + @Override
63.210 + public WizardDescriptor.Panel current() {
63.211 + // wizard title
63.212 + String title = NbBundle.getMessage(NewPythonProjectWizardIterator.class, wizardType == WizardType.APP ? "TXT_PythonProject" : "TXT_ExistingPythonProject");
63.213 + descriptor.putProperty(
63.214 + "NewProjectWizard_Title", title); // NOI18N
63.215 + return panels[index];
63.216 + }
63.217 +
63.218 + @Override
63.219 + public void addChangeListener(ChangeListener l) {
63.220 + }
63.221 +
63.222 + @Override
63.223 + public void removeChangeListener(ChangeListener l) {
63.224 + }
63.225 +
63.226 + static String getFreeFolderName(final File owner, final String proposal) {
63.227 + assert owner != null;
63.228 + assert proposal != null;
63.229 + String freeName = proposal;
63.230 + File f = new File(owner, freeName);
63.231 + int counter = 1;
63.232 + while (f.exists()) {
63.233 + counter++;
63.234 + freeName = proposal + counter;
63.235 + f = new File(owner, freeName);
63.236 + }
63.237 + return freeName;
63.238 +
63.239 + }
63.240 +
63.241 + private WizardDescriptor.Panel[] createPanels() {
63.242 + switch (wizardType) {
63.243 + case APP: {
63.244 + String[] steps = new String[]{
63.245 + NbBundle.getMessage(NewPythonProjectWizardIterator.class, "LBL_ProjectNameLocation"),};
63.246 +
63.247 + PanelConfigureProject configureProjectPanel = new PanelConfigureProject(wizardType, steps);
63.248 + return new WizardDescriptor.Panel[]{
63.249 + configureProjectPanel,};
63.250 + }
63.251 + default:
63.252 + throw new IllegalStateException(wizardType.toString());
63.253 + }
63.254 + }
63.255 +
63.256 + // prevent incorrect default values (empty project => back => existing project)
63.257 + private void initDescriptor(WizardDescriptor settings) {
63.258 + settings.putProperty(PROP_PROJECT_NAME, null);
63.259 + settings.putProperty(PROP_PROJECT_LOCATION, null);
63.260 + }
63.261 +
63.262 + private DataObject createFromTemplate(FileObject template, FileObject sourceDir, String name, Map<String, ? extends Object> parameters) throws IOException {
63.263 + DataFolder dataFolder = DataFolder.findFolder(sourceDir);
63.264 + DataObject dataTemplate = DataObject.find(template);
63.265 + //Strip extension when needed
63.266 + int dot = name.lastIndexOf('.');
63.267 + if (dot > 0 && dot < name.length() - 1 && "py".equalsIgnoreCase(name.substring(dot + 1))) { //NOI18N
63.268 + name = name.substring(0, dot);
63.269 + }
63.270 + if (parameters != null) {
63.271 + return dataTemplate.createFromTemplate(dataFolder, name, parameters);
63.272 + } else {
63.273 + return dataTemplate.createFromTemplate(dataFolder, name);
63.274 + }
63.275 + }
63.276 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/PanelConfigureProject.java Tue Feb 24 01:58:36 2015 -0800
64.3 @@ -0,0 +1,101 @@
64.4 +/*
64.5 + * To change this template, choose Tools | Templates
64.6 + * and open the template in the editor.
64.7 + */
64.8 +package org.netbeans.modules.python.project2.templates;
64.9 +
64.10 +import java.util.HashSet;
64.11 +import java.util.Set;
64.12 +import javax.swing.event.ChangeEvent;
64.13 +import javax.swing.event.ChangeListener;
64.14 +import org.openide.WizardDescriptor;
64.15 +import org.openide.WizardValidationException;
64.16 +import org.openide.util.HelpCtx;
64.17 +
64.18 +/**
64.19 + * Panel just asking for basic info.
64.20 + */
64.21 +public class PanelConfigureProject implements WizardDescriptor.Panel,
64.22 + WizardDescriptor.ValidatingPanel, WizardDescriptor.FinishablePanel {
64.23 +
64.24 + private WizardDescriptor wizardDescriptor;
64.25 + private PanelConfigureProjectVisual component;
64.26 + private final NewPythonProjectWizardIterator.WizardType type;
64.27 + private final String[] steps;
64.28 +
64.29 + public PanelConfigureProject (final NewPythonProjectWizardIterator.WizardType type, String[] steps) {
64.30 + assert type != null;
64.31 + assert steps != null;
64.32 + this.type = type;
64.33 + this.steps = steps;
64.34 + }
64.35 +
64.36 + @Override
64.37 + public PanelConfigureProjectVisual getComponent() {
64.38 + if (component == null) {
64.39 + component = new PanelConfigureProjectVisual(this, type);
64.40 + component.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
64.41 + }
64.42 + return component;
64.43 + }
64.44 +
64.45 + @Override
64.46 + public HelpCtx getHelp() {
64.47 + return new HelpCtx("org.netbeans.modules.python.project2.templates.PanelConfigureProject");
64.48 + }
64.49 +
64.50 + @Override
64.51 + public boolean isValid() {
64.52 + getComponent();
64.53 + return getComponent().valid(wizardDescriptor);
64.54 + }
64.55 + private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
64.56 +
64.57 + @Override
64.58 + public final void addChangeListener(ChangeListener l) {
64.59 + synchronized (listeners) {
64.60 + listeners.add(l);
64.61 + }
64.62 + }
64.63 +
64.64 + @Override
64.65 + public final void removeChangeListener(ChangeListener l) {
64.66 + synchronized (listeners) {
64.67 + listeners.remove(l);
64.68 + }
64.69 + }
64.70 +
64.71 + protected final void fireChangeEvent() {
64.72 + Set<ChangeListener> ls;
64.73 + synchronized (listeners) {
64.74 + ls = new HashSet<>(listeners);
64.75 + }
64.76 + ChangeEvent ev = new ChangeEvent(this);
64.77 + for (ChangeListener l : ls) {
64.78 + l.stateChanged(ev);
64.79 + }
64.80 + }
64.81 +
64.82 + @Override
64.83 + public void readSettings(Object settings) {
64.84 + wizardDescriptor = (WizardDescriptor) settings;
64.85 + getComponent().read(wizardDescriptor);
64.86 + }
64.87 +
64.88 + @Override
64.89 + public void storeSettings(Object settings) {
64.90 + WizardDescriptor d = (WizardDescriptor) settings;
64.91 + getComponent().store(d);
64.92 + }
64.93 +
64.94 + @Override
64.95 + public boolean isFinishPanel() {
64.96 + return true;
64.97 + }
64.98 +
64.99 + @Override
64.100 + public void validate() throws WizardValidationException {
64.101 + getComponent();
64.102 + getComponent().validate(wizardDescriptor);
64.103 + }
64.104 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/PanelConfigureProjectVisual.form Tue Feb 24 01:58:36 2015 -0800
65.3 @@ -0,0 +1,60 @@
65.4 +<?xml version="1.0" encoding="UTF-8" ?>
65.5 +
65.6 +<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
65.7 + <AuxValues>
65.8 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
65.9 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
65.10 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
65.11 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
65.12 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
65.13 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
65.14 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
65.15 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
65.16 + <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
65.17 + </AuxValues>
65.18 +
65.19 + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
65.20 + <SubComponents>
65.21 + <Container class="javax.swing.JPanel" name="locationContainer">
65.22 + <AccessibilityProperties>
65.23 + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
65.24 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSN_locationContainer" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
65.25 + </Property>
65.26 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
65.27 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSD_locationContainer" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
65.28 + </Property>
65.29 + </AccessibilityProperties>
65.30 + <Constraints>
65.31 + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
65.32 + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
65.33 + </Constraint>
65.34 + </Constraints>
65.35 +
65.36 + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
65.37 + </Container>
65.38 + <Component class="javax.swing.JSeparator" name="jSeparator1">
65.39 + <Constraints>
65.40 + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
65.41 + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="12" insetsLeft="0" insetsBottom="12" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
65.42 + </Constraint>
65.43 + </Constraints>
65.44 + </Component>
65.45 + <Container class="javax.swing.JPanel" name="optionsContainer">
65.46 + <AccessibilityProperties>
65.47 + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
65.48 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSN_optionsContainer" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
65.49 + </Property>
65.50 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
65.51 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSD_optionsContainer" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
65.52 + </Property>
65.53 + </AccessibilityProperties>
65.54 + <Constraints>
65.55 + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
65.56 + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="0" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="1.0"/>
65.57 + </Constraint>
65.58 + </Constraints>
65.59 +
65.60 + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
65.61 + </Container>
65.62 + </SubComponents>
65.63 +</Form>
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/PanelConfigureProjectVisual.java Tue Feb 24 01:58:36 2015 -0800
66.3 @@ -0,0 +1,169 @@
66.4 +/*
66.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
66.6 + *
66.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
66.8 + *
66.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
66.10 + * Other names may be trademarks of their respective owners.
66.11 + *
66.12 + * The contents of this file are subject to the terms of either the GNU
66.13 + * General Public License Version 2 only ("GPL") or the Common
66.14 + * Development and Distribution License("CDDL") (collectively, the
66.15 + * "License"). You may not use this file except in compliance with the
66.16 + * License. You can obtain a copy of the License at
66.17 + * http://www.netbeans.org/cddl-gplv2.html
66.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
66.19 + * specific language governing permissions and limitations under the
66.20 + * License. When distributing the software, include this License Header
66.21 + * Notice in each file and include the License file at
66.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
66.23 + * particular file as subject to the "Classpath" exception as provided
66.24 + * by Oracle in the GPL Version 2 section of the License file that
66.25 + * accompanied this code. If applicable, add the following below the
66.26 + * License Header, with the fields enclosed by brackets [] replaced by
66.27 + * your own identifying information:
66.28 + * "Portions Copyrighted [year] [name of copyright owner]"
66.29 + *
66.30 + * Contributor(s):
66.31 + *
66.32 + * The Original Software is NetBeans. The Initial Developer of the Original
66.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
66.34 + * Microsystems, Inc. All Rights Reserved.
66.35 + *
66.36 + * If you wish your version of this file to be governed by only the CDDL
66.37 + * or only the GPL Version 2, indicate your decision by adding
66.38 + * "[Contributor] elects to include this software in this distribution
66.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
66.40 + * single choice of license, a recipient has the option to distribute
66.41 + * your version of this file under either the CDDL, the GPL Version 2 or
66.42 + * to extend the choice of license to its licensees as provided above.
66.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
66.44 + * Version 2 license, then the option applies only if the new code is
66.45 + * made subject to such option by the copyright holder.
66.46 + */
66.47 +
66.48 +package org.netbeans.modules.python.project2.templates;
66.49 +
66.50 +import javax.swing.JPanel;
66.51 +import org.openide.WizardDescriptor;
66.52 +import org.openide.WizardValidationException;
66.53 +import org.openide.util.NbBundle;
66.54 +
66.55 +/** First panel in the NewProject wizard. Used for filling in
66.56 + * name, and directory of the project.
66.57 + *
66.58 + * @author Tomas Zezula
66.59 + */
66.60 +public class PanelConfigureProjectVisual extends JPanel {
66.61 +
66.62 + private PanelConfigureProject panel;
66.63 +
66.64 + private SettingsPanel projectLocationPanel;
66.65 +
66.66 + private PanelOptionsVisual optionsPanel;
66.67 +
66.68 + private NewPythonProjectWizardIterator.WizardType type;
66.69 +
66.70 + public PanelConfigureProjectVisual(PanelConfigureProject panel, NewPythonProjectWizardIterator.WizardType type) {
66.71 + this.panel = panel;
66.72 + initComponents();
66.73 + this.type = type;
66.74 + setName(NbBundle.getMessage(PanelConfigureProjectVisual.class,"TXT_NameAndLoc")); // NOI18N
66.75 + switch (type) {
66.76 + case APP:
66.77 + projectLocationPanel = new EmptyPythonProjectPanelVisual(panel);
66.78 + putClientProperty ("NewProjectWizard_Title", NbBundle.getMessage(PanelConfigureProjectVisual.class,"TXT_NewPythonApp")); // NOI18N
66.79 + jSeparator1.setVisible(true);
66.80 + getAccessibleContext ().setAccessibleName (NbBundle.getMessage(PanelConfigureProjectVisual.class,"TXT_NewPythonApp")); // NOI18N
66.81 + getAccessibleContext ().setAccessibleDescription (NbBundle.getMessage(PanelConfigureProjectVisual.class,"ACSD_NewPythonApp")); // NOI18N
66.82 + break;
66.83 + default:
66.84 + throw new UnsupportedOperationException();
66.85 + }
66.86 + locationContainer.add( projectLocationPanel, java.awt.BorderLayout.CENTER );
66.87 + optionsPanel = new PanelOptionsVisual( panel, type );
66.88 + projectLocationPanel.addPropertyChangeListener(optionsPanel);
66.89 + optionsContainer.add( optionsPanel, java.awt.BorderLayout.CENTER );
66.90 + }
66.91 +
66.92 + boolean valid( WizardDescriptor wizardDescriptor ) {
66.93 + wizardDescriptor.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, ""); //NOI18N
66.94 + return projectLocationPanel.valid( wizardDescriptor ) && optionsPanel.valid(wizardDescriptor);
66.95 + }
66.96 +
66.97 + void read (WizardDescriptor d) {
66.98 + Object lastType = d.getProperty("wizard-type"); //NOI18N
66.99 + if (lastType == null || lastType != type) {
66.100 + //bugfix #46387 The type of project changed, reset values to defaults
66.101 + d.putProperty ("name", null);
66.102 + d.putProperty ("projdir",null);
66.103 + }
66.104 + projectLocationPanel.read (d);
66.105 + optionsPanel.read (d);
66.106 + }
66.107 +
66.108 + void store( WizardDescriptor d ) {
66.109 + d.putProperty("wizard-type", type); //NOI18N
66.110 + projectLocationPanel.store( d );
66.111 + optionsPanel.store( d );
66.112 + }
66.113 +
66.114 + void validate (WizardDescriptor d) throws WizardValidationException {
66.115 + projectLocationPanel.validate (d);
66.116 + }
66.117 +
66.118 +
66.119 + /** This method is called from within the constructor to
66.120 + * initialize the form.
66.121 + * WARNING: Do NOT modify this code. The content of this method is
66.122 + * always regenerated by the Form Editor.
66.123 + */
66.124 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
66.125 + private void initComponents() {
66.126 + java.awt.GridBagConstraints gridBagConstraints;
66.127 +
66.128 + locationContainer = new javax.swing.JPanel();
66.129 + jSeparator1 = new javax.swing.JSeparator();
66.130 + optionsContainer = new javax.swing.JPanel();
66.131 +
66.132 + setLayout(new java.awt.GridBagLayout());
66.133 +
66.134 + locationContainer.setLayout(new java.awt.BorderLayout());
66.135 + gridBagConstraints = new java.awt.GridBagConstraints();
66.136 + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
66.137 + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
66.138 + gridBagConstraints.weightx = 1.0;
66.139 + add(locationContainer, gridBagConstraints);
66.140 + locationContainer.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getBundle(PanelConfigureProjectVisual.class).getString("ACSN_locationContainer")); // NOI18N
66.141 + locationContainer.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(PanelConfigureProjectVisual.class).getString("ACSD_locationContainer")); // NOI18N
66.142 +
66.143 + gridBagConstraints = new java.awt.GridBagConstraints();
66.144 + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
66.145 + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
66.146 + gridBagConstraints.weightx = 1.0;
66.147 + gridBagConstraints.insets = new java.awt.Insets(12, 0, 12, 0);
66.148 + add(jSeparator1, gridBagConstraints);
66.149 +
66.150 + optionsContainer.setLayout(new java.awt.BorderLayout());
66.151 + gridBagConstraints = new java.awt.GridBagConstraints();
66.152 + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
66.153 + gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
66.154 + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
66.155 + gridBagConstraints.weightx = 1.0;
66.156 + gridBagConstraints.weighty = 1.0;
66.157 + add(optionsContainer, gridBagConstraints);
66.158 + optionsContainer.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getBundle(PanelConfigureProjectVisual.class).getString("ACSN_optionsContainer")); // NOI18N
66.159 + optionsContainer.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(PanelConfigureProjectVisual.class).getString("ACSD_optionsContainer")); // NOI18N
66.160 + }// </editor-fold>//GEN-END:initComponents
66.161 +
66.162 + /** Currently only handles the "Browse..." button
66.163 + */
66.164 +
66.165 + // Variables declaration - do not modify//GEN-BEGIN:variables
66.166 + private javax.swing.JSeparator jSeparator1;
66.167 + private javax.swing.JPanel locationContainer;
66.168 + private javax.swing.JPanel optionsContainer;
66.169 + // End of variables declaration//GEN-END:variables
66.170 +
66.171 +
66.172 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/PanelOptionsVisual.form Tue Feb 24 01:58:36 2015 -0800
67.3 @@ -0,0 +1,125 @@
67.4 +<?xml version="1.0" encoding="UTF-8" ?>
67.5 +
67.6 +<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
67.7 + <AccessibilityProperties>
67.8 + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.9 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSN_PanelOptionsVisual" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
67.10 + </Property>
67.11 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.12 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSD_PanelOptionsVisual" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
67.13 + </Property>
67.14 + </AccessibilityProperties>
67.15 + <AuxValues>
67.16 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
67.17 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
67.18 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
67.19 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
67.20 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
67.21 + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
67.22 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
67.23 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
67.24 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
67.25 + </AuxValues>
67.26 +
67.27 + <Layout>
67.28 + <DimensionLayout dim="0">
67.29 + <Group type="103" groupAlignment="0" attributes="0">
67.30 + <Group type="102" alignment="0" attributes="0">
67.31 + <Group type="103" groupAlignment="0" attributes="0">
67.32 + <Component id="createMainCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
67.33 + <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
67.34 + </Group>
67.35 + <EmptySpace type="separate" max="-2" attributes="0"/>
67.36 + <Group type="103" groupAlignment="0" attributes="0">
67.37 + <Group type="102" attributes="0">
67.38 + <Component id="platforms" min="-2" pref="233" max="-2" attributes="0"/>
67.39 + <EmptySpace type="unrelated" max="-2" attributes="0"/>
67.40 + <Component id="manage" min="-2" max="-2" attributes="0"/>
67.41 + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
67.42 + </Group>
67.43 + <Component id="mainFileTextField" alignment="0" max="32767" attributes="0"/>
67.44 + </Group>
67.45 + </Group>
67.46 + </Group>
67.47 + </DimensionLayout>
67.48 + <DimensionLayout dim="1">
67.49 + <Group type="103" groupAlignment="0" attributes="0">
67.50 + <Group type="102" attributes="0">
67.51 + <EmptySpace max="-2" attributes="0"/>
67.52 + <Group type="103" groupAlignment="3" attributes="0">
67.53 + <Component id="createMainCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
67.54 + <Component id="mainFileTextField" alignment="3" min="-2" max="-2" attributes="0"/>
67.55 + </Group>
67.56 + <EmptySpace max="-2" attributes="0"/>
67.57 + <Group type="103" groupAlignment="0" attributes="0">
67.58 + <Group type="103" groupAlignment="3" attributes="0">
67.59 + <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
67.60 + <Component id="platforms" alignment="3" min="-2" max="-2" attributes="0"/>
67.61 + </Group>
67.62 + <Component id="manage" alignment="0" min="-2" max="-2" attributes="0"/>
67.63 + </Group>
67.64 + <EmptySpace max="32767" attributes="0"/>
67.65 + </Group>
67.66 + </Group>
67.67 + </DimensionLayout>
67.68 + </Layout>
67.69 + <SubComponents>
67.70 + <Component class="javax.swing.JCheckBox" name="createMainCheckBox">
67.71 + <Properties>
67.72 + <Property name="selected" type="boolean" value="true"/>
67.73 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.74 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="LBL_createMainCheckBox" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
67.75 + </Property>
67.76 + </Properties>
67.77 + <AccessibilityProperties>
67.78 + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.79 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSN_createMainCheckBox" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
67.80 + </Property>
67.81 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.82 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ACSD_createMainCheckBox" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
67.83 + </Property>
67.84 + </AccessibilityProperties>
67.85 + <AuxValues>
67.86 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
67.87 + </AuxValues>
67.88 + </Component>
67.89 + <Component class="javax.swing.JTextField" name="mainFileTextField">
67.90 + <Properties>
67.91 + <Property name="text" type="java.lang.String" value="main"/>
67.92 + </Properties>
67.93 + <AccessibilityProperties>
67.94 + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.95 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ASCN_mainClassTextFiled" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
67.96 + </Property>
67.97 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.98 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="ASCD_mainClassTextFiled" replaceFormat="org.openide.util.NbBundle.getBundle({sourceFileName}.class).getString("{key}")"/>
67.99 + </Property>
67.100 + </AccessibilityProperties>
67.101 + </Component>
67.102 + <Component class="javax.swing.JLabel" name="jLabel1">
67.103 + <Properties>
67.104 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
67.105 + <ComponentRef name="platforms"/>
67.106 + </Property>
67.107 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.108 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="TXT_PythonPlatform" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
67.109 + </Property>
67.110 + </Properties>
67.111 + </Component>
67.112 + <Component class="javax.swing.JComboBox" name="platforms">
67.113 + <AuxValues>
67.114 + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="org.netbeans.modules.python.api.PlatformComponentFactory.getPythonPlatformsComboxBox()"/>
67.115 + </AuxValues>
67.116 + </Component>
67.117 + <Component class="javax.swing.JButton" name="manage">
67.118 + <Properties>
67.119 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
67.120 + <ResourceString bundle="org/netbeans/modules/python/project2/templates/Bundle.properties" key="TXT_ManagePlatfroms" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
67.121 + </Property>
67.122 + </Properties>
67.123 + <Events>
67.124 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="manageActionPerformed"/>
67.125 + </Events>
67.126 + </Component>
67.127 + </SubComponents>
67.128 +</Form>
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/PanelOptionsVisual.java Tue Feb 24 01:58:36 2015 -0800
68.3 @@ -0,0 +1,349 @@
68.4 +/*
68.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
68.6 + *
68.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
68.8 + *
68.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
68.10 + * Other names may be trademarks of their respective owners.
68.11 + *
68.12 + * The contents of this file are subject to the terms of either the GNU
68.13 + * General Public License Version 2 only ("GPL") or the Common
68.14 + * Development and Distribution License("CDDL") (collectively, the
68.15 + * "License"). You may not use this file except in compliance with the
68.16 + * License. You can obtain a copy of the License at
68.17 + * http://www.netbeans.org/cddl-gplv2.html
68.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
68.19 + * specific language governing permissions and limitations under the
68.20 + * License. When distributing the software, include this License Header
68.21 + * Notice in each file and include the License file at
68.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
68.23 + * particular file as subject to the "Classpath" exception as provided
68.24 + * by Oracle in the GPL Version 2 section of the License file that
68.25 + * accompanied this code. If applicable, add the following below the
68.26 + * License Header, with the fields enclosed by brackets [] replaced by
68.27 + * your own identifying information:
68.28 + * "Portions Copyrighted [year] [name of copyright owner]"
68.29 + *
68.30 + * Contributor(s):
68.31 + *
68.32 + * The Original Software is NetBeans. The Initial Developer of the Original
68.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
68.34 + * Microsystems, Inc. All Rights Reserved.
68.35 + *
68.36 + * If you wish your version of this file to be governed by only the CDDL
68.37 + * or only the GPL Version 2, indicate your decision by adding
68.38 + * "[Contributor] elects to include this software in this distribution
68.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
68.40 + * single choice of license, a recipient has the option to distribute
68.41 + * your version of this file under either the CDDL, the GPL Version 2 or
68.42 + * to extend the choice of license to its licensees as provided above.
68.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
68.44 + * Version 2 license, then the option applies only if the new code is
68.45 + * made subject to such option by the copyright holder.
68.46 + */
68.47 +
68.48 +
68.49 +package org.netbeans.modules.python.project2.templates;
68.50 +
68.51 +import java.awt.event.ActionEvent;
68.52 +import java.awt.event.ActionListener;
68.53 +import java.beans.PropertyChangeEvent;
68.54 +import java.beans.PropertyChangeListener;
68.55 +import java.io.IOException;
68.56 +import java.util.StringTokenizer;
68.57 +import javax.swing.JComboBox;
68.58 +import javax.swing.event.DocumentListener;
68.59 +import javax.swing.event.DocumentEvent;
68.60 +import org.netbeans.modules.python.api.PlatformComponentFactory;
68.61 +import org.netbeans.modules.python.api.PythonPlatform;
68.62 +import org.netbeans.modules.python.api.PythonPlatformManager;
68.63 +import org.netbeans.modules.python.api.Util;
68.64 +import org.netbeans.modules.python.project2.ui.Utils;
68.65 +import org.openide.WizardDescriptor;
68.66 +import org.openide.WizardValidationException;
68.67 +import org.openide.filesystems.FileObject;
68.68 +import org.openide.filesystems.FileUtil;
68.69 +import org.openide.loaders.DataObject;
68.70 +import org.openide.loaders.InstanceDataObject;
68.71 +import org.openide.util.Exceptions;
68.72 +import org.openide.util.NbBundle;
68.73 +import org.openide.util.Utilities;
68.74 +import org.openide.util.actions.CallableSystemAction;
68.75 +
68.76 +/**
68.77 + * @author Tomas Zezula
68.78 + */
68.79 +public final class PanelOptionsVisual extends SettingsPanel implements ActionListener, PropertyChangeListener {
68.80 +
68.81 + private static boolean lastMainClassCheck = true; // XXX Store somewhere
68.82 +
68.83 + private PanelConfigureProject panel;
68.84 + private boolean valid;
68.85 + private String projectLocation;
68.86 +
68.87 + public PanelOptionsVisual(PanelConfigureProject panel, NewPythonProjectWizardIterator.WizardType type) {
68.88 + initComponents();
68.89 + this.panel = panel;
68.90 + PlatformComponentFactory.addPlatformChangeListener(platforms, new PlatformComponentFactory.PlatformChangeListener() {
68.91 + @Override
68.92 + public void platformChanged() {
68.93 + fireChangeEvent();
68.94 + }
68.95 + });
68.96 +
68.97 +
68.98 + switch (type) {
68.99 + case APP:
68.100 + createMainCheckBox.addActionListener( this );
68.101 + createMainCheckBox.setSelected( lastMainClassCheck );
68.102 + mainFileTextField.setEnabled( lastMainClassCheck );
68.103 + break;
68.104 + }
68.105 +
68.106 + this.mainFileTextField.getDocument().addDocumentListener( new DocumentListener () {
68.107 +
68.108 + @Override
68.109 + public void insertUpdate(DocumentEvent e) {
68.110 + mainFileChanged ();
68.111 + }
68.112 +
68.113 + @Override
68.114 + public void removeUpdate(DocumentEvent e) {
68.115 + mainFileChanged ();
68.116 + }
68.117 +
68.118 + @Override
68.119 + public void changedUpdate(DocumentEvent e) {
68.120 + mainFileChanged ();
68.121 + }
68.122 +
68.123 + });
68.124 +
68.125 + }
68.126 +
68.127 + @Override
68.128 + public void actionPerformed( ActionEvent e ) {
68.129 + if ( e.getSource() == createMainCheckBox ) {
68.130 + lastMainClassCheck = createMainCheckBox.isSelected();
68.131 + mainFileTextField.setEnabled( lastMainClassCheck );
68.132 + this.panel.fireChangeEvent();
68.133 + }
68.134 + }
68.135 +
68.136 + @Override
68.137 + public void propertyChange (PropertyChangeEvent event) {
68.138 + // The project name isn't very python'y
68.139 + if (NewPythonProjectWizardIterator.PROP_PROJECT_NAME.equals(event.getPropertyName())) {
68.140 + String newProjectName = (String) event.getNewValue();
68.141 + this.mainFileTextField.setText (NbBundle.getMessage(PanelOptionsVisual.class, "TXT_MainFileName",newProjectName.toLowerCase()));
68.142 + }
68.143 + if (NewPythonProjectWizardIterator.PROP_PROJECT_LOCATION.equals(event.getPropertyName())) {
68.144 + projectLocation = (String)event.getNewValue();
68.145 + }
68.146 + }
68.147 +
68.148 + /** This method is called from within the constructor to
68.149 + * initialize the form.
68.150 + * WARNING: Do NOT modify this code. The content of this method is
68.151 + * always regenerated by the Form Editor.
68.152 + */
68.153 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
68.154 + private void initComponents() {
68.155 +
68.156 + createMainCheckBox = new javax.swing.JCheckBox();
68.157 + mainFileTextField = new javax.swing.JTextField();
68.158 + jLabel1 = new javax.swing.JLabel();
68.159 + platforms = org.netbeans.modules.python.api.PlatformComponentFactory.getPythonPlatformsComboxBox();
68.160 + manage = new javax.swing.JButton();
68.161 +
68.162 + createMainCheckBox.setSelected(true);
68.163 + org.openide.awt.Mnemonics.setLocalizedText(createMainCheckBox, org.openide.util.NbBundle.getBundle(PanelOptionsVisual.class).getString("LBL_createMainCheckBox")); // NOI18N
68.164 +
68.165 + mainFileTextField.setText("main");
68.166 +
68.167 + jLabel1.setLabelFor(platforms);
68.168 + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PanelOptionsVisual.class, "TXT_PythonPlatform")); // NOI18N
68.169 +
68.170 + org.openide.awt.Mnemonics.setLocalizedText(manage, org.openide.util.NbBundle.getMessage(PanelOptionsVisual.class, "TXT_ManagePlatfroms")); // NOI18N
68.171 + manage.addActionListener(new java.awt.event.ActionListener() {
68.172 + public void actionPerformed(java.awt.event.ActionEvent evt) {
68.173 + manageActionPerformed(evt);
68.174 + }
68.175 + });
68.176 +
68.177 + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
68.178 + this.setLayout(layout);
68.179 + layout.setHorizontalGroup(
68.180 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68.181 + .addGroup(layout.createSequentialGroup()
68.182 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68.183 + .addComponent(createMainCheckBox)
68.184 + .addComponent(jLabel1))
68.185 + .addGap(18, 18, 18)
68.186 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68.187 + .addGroup(layout.createSequentialGroup()
68.188 + .addComponent(platforms, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE)
68.189 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
68.190 + .addComponent(manage)
68.191 + .addGap(4, 4, 4))
68.192 + .addComponent(mainFileTextField)))
68.193 + );
68.194 + layout.setVerticalGroup(
68.195 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68.196 + .addGroup(layout.createSequentialGroup()
68.197 + .addContainerGap()
68.198 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
68.199 + .addComponent(createMainCheckBox)
68.200 + .addComponent(mainFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
68.201 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
68.202 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
68.203 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
68.204 + .addComponent(jLabel1)
68.205 + .addComponent(platforms, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
68.206 + .addComponent(manage))
68.207 + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
68.208 + );
68.209 +
68.210 + createMainCheckBox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getBundle(PanelOptionsVisual.class).getString("ACSN_createMainCheckBox")); // NOI18N
68.211 + createMainCheckBox.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(PanelOptionsVisual.class).getString("ACSD_createMainCheckBox")); // NOI18N
68.212 + mainFileTextField.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getBundle(PanelOptionsVisual.class).getString("ASCN_mainClassTextFiled")); // NOI18N
68.213 + mainFileTextField.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getBundle(PanelOptionsVisual.class).getString("ASCD_mainClassTextFiled")); // NOI18N
68.214 +
68.215 + getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(PanelOptionsVisual.class, "ACSN_PanelOptionsVisual")); // NOI18N
68.216 + getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(PanelOptionsVisual.class, "ACSD_PanelOptionsVisual")); // NOI18N
68.217 + }// </editor-fold>//GEN-END:initComponents
68.218 +
68.219 +private void manageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageActionPerformed
68.220 +//Workaround, Needs an API to display platform customizer
68.221 + final FileObject fo = FileUtil.getConfigFile("Actions/Python/org-netbeans-modules-python-platform-PythonManagerAction.instance"); //NOI18N
68.222 + if (fo != null) {
68.223 + try {
68.224 + InstanceDataObject ido = (InstanceDataObject) DataObject.find(fo);
68.225 + CallableSystemAction action = (CallableSystemAction) ido.instanceCreate();
68.226 + action.performAction();
68.227 + platforms.setModel(Utils.createPlatformModel()); //Currentl the PythonManager doesn't fire events, we need to replace model.
68.228 + } catch (IOException | ClassNotFoundException ex) {
68.229 + Exceptions.printStackTrace(ex);
68.230 + }
68.231 + }
68.232 +}//GEN-LAST:event_manageActionPerformed
68.233 +
68.234 +
68.235 +
68.236 + @Override
68.237 + boolean valid(WizardDescriptor settings) {
68.238 + if (PlatformComponentFactory.getPlatform(platforms) == null) {
68.239 + // Only complain if there are no available platforms since most likely there's
68.240 + // no selection yet because it's busy auto-detecting
68.241 + if (PythonPlatformManager.getInstance().getPlatformList().isEmpty()) {
68.242 + settings.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE,
68.243 + NbBundle.getMessage(PanelOptionsVisual.class,"ERROR_IllegalPlatform"));
68.244 + }
68.245 + return false;
68.246 + }
68.247 + if (mainFileTextField.isVisible () && mainFileTextField.isEnabled ()) {
68.248 + if (!valid) {
68.249 + settings.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE,
68.250 + NbBundle.getMessage(PanelOptionsVisual.class,"ERROR_IllegalMainFileName")); //NOI18N
68.251 + }
68.252 + return this.valid;
68.253 + }
68.254 + else {
68.255 + return true;
68.256 + }
68.257 + }
68.258 +
68.259 + @Override
68.260 + void read (WizardDescriptor d) {
68.261 + final PythonPlatformManager manager = PythonPlatformManager.getInstance();
68.262 + String pid = (String) d.getProperty(NewPythonProjectWizardIterator.PROP_PLATFORM_ID);
68.263 + if (pid == null) {
68.264 + pid = Util.getPythonPreferences().get(LAST_PLATFORM_ID, null);
68.265 + if (pid == null) {
68.266 + pid = manager.getDefaultPlatform();
68.267 + }
68.268 + }
68.269 + final PythonPlatform activePlatform = manager.getPlatform(pid);
68.270 + if (activePlatform != null) {
68.271 + platforms.setSelectedItem(activePlatform);
68.272 + }
68.273 + }
68.274 +
68.275 + @Override
68.276 + void validate (WizardDescriptor d) throws WizardValidationException {
68.277 + // nothing to validate
68.278 + }
68.279 +
68.280 + @Override
68.281 + void store( WizardDescriptor d ) {
68.282 + d.putProperty(NewPythonProjectWizardIterator.PROP_MAIN_FILE, createMainCheckBox.isSelected() && createMainCheckBox.isVisible() ? mainFileTextField.getText() : null ); // NOI18N
68.283 + PythonPlatform platform = PlatformComponentFactory.getPlatform(platforms);
68.284 + if (platform != null) {
68.285 + d.putProperty(NewPythonProjectWizardIterator.PROP_PLATFORM_ID, platform.getId());
68.286 + }
68.287 + }
68.288 +
68.289 + // Variables declaration - do not modify//GEN-BEGIN:variables
68.290 + private javax.swing.JCheckBox createMainCheckBox;
68.291 + private javax.swing.JLabel jLabel1;
68.292 + private javax.swing.JTextField mainFileTextField;
68.293 + private javax.swing.JButton manage;
68.294 + private javax.swing.JComboBox platforms;
68.295 + // End of variables declaration//GEN-END:variables
68.296 +
68.297 + private void mainFileChanged () {
68.298 + String mainClassName = this.mainFileTextField.getText ();
68.299 + StringTokenizer tk = new StringTokenizer (mainClassName, "."); //NOI18N
68.300 + boolean isJavaIdentifier = true;
68.301 + while (tk.hasMoreTokens()) {
68.302 + String token = tk.nextToken();
68.303 + if (token.length() == 0 || !Utilities.isJavaIdentifier(token)) {
68.304 + isJavaIdentifier = false;
68.305 + break;
68.306 + }
68.307 + }
68.308 + this.valid = isJavaIdentifier;
68.309 + this.panel.fireChangeEvent();
68.310 + }
68.311 +
68.312 + public @Override void removeNotify() {
68.313 + storeWizardPlatform(platforms);
68.314 + super.removeNotify();
68.315 + }
68.316 +
68.317 + private void fireChangeEvent() {
68.318 + this.panel.fireChangeEvent();
68.319 + }
68.320 +
68.321 + private static final String LAST_PLATFORM_ID = "projectPanelLastPlatformID"; // NOI18N
68.322 +
68.323 + public static void preselectWizardPlatform(final JComboBox platforms) {
68.324 + preselectPlatform(platforms, LAST_PLATFORM_ID);
68.325 + }
68.326 +
68.327 + public static void preselectPlatform(final JComboBox platforms, final String preferencePlatformIDKey) {
68.328 + String lastPlatformID = Util.getPythonPreferences().get(preferencePlatformIDKey, null);
68.329 + if (lastPlatformID != null) {
68.330 + PythonPlatform platform = PythonPlatformManager.getInstance().getPlatform(lastPlatformID);
68.331 + if (platform != null) {
68.332 + platforms.setSelectedItem(platform);
68.333 + }
68.334 + }
68.335 + }
68.336 +
68.337 + public static void storeWizardPlatform(JComboBox platforms) {
68.338 + PythonPlatform selectedPlatform = PlatformComponentFactory.getPlatform(platforms);
68.339 + if (selectedPlatform != null) {
68.340 + Util.getPythonPreferences().put(LAST_PLATFORM_ID, selectedPlatform.getId());
68.341 + }
68.342 + }
68.343 +
68.344 +//
68.345 +// public static void storeWizardPlatform(JComboBox platforms) {
68.346 +// PythonPlatform selectedPlatform = PlatformComponentFactory.getPlatform(platforms);
68.347 +// if (selectedPlatform != null) {
68.348 +// RubyPreferences.getPreferences().put(LAST_PLATFORM_ID, selectedPlatform.getID());
68.349 +// }
68.350 +// }
68.351 +}
68.352 +
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/templates/SettingsPanel.java Tue Feb 24 01:58:36 2015 -0800
69.3 @@ -0,0 +1,64 @@
69.4 +/*
69.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
69.6 + *
69.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
69.8 + *
69.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
69.10 + * Other names may be trademarks of their respective owners.
69.11 + *
69.12 + * The contents of this file are subject to the terms of either the GNU
69.13 + * General Public License Version 2 only ("GPL") or the Common
69.14 + * Development and Distribution License("CDDL") (collectively, the
69.15 + * "License"). You may not use this file except in compliance with the
69.16 + * License. You can obtain a copy of the License at
69.17 + * http://www.netbeans.org/cddl-gplv2.html
69.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
69.19 + * specific language governing permissions and limitations under the
69.20 + * License. When distributing the software, include this License Header
69.21 + * Notice in each file and include the License file at
69.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
69.23 + * particular file as subject to the "Classpath" exception as provided
69.24 + * by Oracle in the GPL Version 2 section of the License file that
69.25 + * accompanied this code. If applicable, add the following below the
69.26 + * License Header, with the fields enclosed by brackets [] replaced by
69.27 + * your own identifying information:
69.28 + * "Portions Copyrighted [year] [name of copyright owner]"
69.29 + *
69.30 + * Contributor(s):
69.31 + *
69.32 + * The Original Software is NetBeans. The Initial Developer of the Original
69.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
69.34 + * Microsystems, Inc. All Rights Reserved.
69.35 + *
69.36 + * If you wish your version of this file to be governed by only the CDDL
69.37 + * or only the GPL Version 2, indicate your decision by adding
69.38 + * "[Contributor] elects to include this software in this distribution
69.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
69.40 + * single choice of license, a recipient has the option to distribute
69.41 + * your version of this file under either the CDDL, the GPL Version 2 or
69.42 + * to extend the choice of license to its licensees as provided above.
69.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
69.44 + * Version 2 license, then the option applies only if the new code is
69.45 + * made subject to such option by the copyright holder.
69.46 + */
69.47 +
69.48 +package org.netbeans.modules.python.project2.templates;
69.49 +
69.50 +import javax.swing.JPanel;
69.51 +import org.openide.WizardDescriptor;
69.52 +import org.openide.WizardValidationException;
69.53 +
69.54 +/**
69.55 + *
69.56 + * @author Tomas Zezula
69.57 + */
69.58 +abstract class SettingsPanel extends JPanel {
69.59 +
69.60 + abstract void store (WizardDescriptor settings);
69.61 +
69.62 + abstract void read (WizardDescriptor settings);
69.63 +
69.64 + abstract boolean valid (WizardDescriptor settings);
69.65 +
69.66 + abstract void validate (WizardDescriptor settings) throws WizardValidationException;
69.67 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/Bundle.properties Tue Feb 24 01:58:36 2015 -0800
70.3 @@ -0,0 +1,5 @@
70.4 +# To change this license header, choose License Headers in Project Properties.
70.5 +# To change this template file, choose Tools | Templates
70.6 +# and open the template in the editor.
70.7 +
70.8 +MainModuleChooser.jLabel1.text=&Main Modules:
70.9 \ No newline at end of file
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/ChangePackageViewTypeAction.java Tue Feb 24 01:58:36 2015 -0800
71.3 @@ -0,0 +1,101 @@
71.4 +/*
71.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
71.6 + *
71.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
71.8 + *
71.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
71.10 + * Other names may be trademarks of their respective owners.
71.11 + *
71.12 + * The contents of this file are subject to the terms of either the GNU
71.13 + * General Public License Version 2 only ("GPL") or the Common
71.14 + * Development and Distribution License("CDDL") (collectively, the
71.15 + * "License"). You may not use this file except in compliance with the
71.16 + * License. You can obtain a copy of the License at
71.17 + * http://www.netbeans.org/cddl-gplv2.html
71.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
71.19 + * specific language governing permissions and limitations under the
71.20 + * License. When distributing the software, include this License Header
71.21 + * Notice in each file and include the License file at
71.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
71.23 + * particular file as subject to the "Classpath" exception as provided
71.24 + * by Oracle in the GPL Version 2 section of the License file that
71.25 + * accompanied this code. If applicable, add the following below the
71.26 + * License Header, with the fields enclosed by brackets [] replaced by
71.27 + * your own identifying information:
71.28 + * "Portions Copyrighted [year] [name of copyright owner]"
71.29 + *
71.30 + * Contributor(s):
71.31 + *
71.32 + * The Original Software is NetBeans. The Initial Developer of the Original
71.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
71.34 + * Microsystems, Inc. All Rights Reserved.
71.35 + *
71.36 + * If you wish your version of this file to be governed by only the CDDL
71.37 + * or only the GPL Version 2, indicate your decision by adding
71.38 + * "[Contributor] elects to include this software in this distribution
71.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
71.40 + * single choice of license, a recipient has the option to distribute
71.41 + * your version of this file under either the CDDL, the GPL Version 2 or
71.42 + * to extend the choice of license to its licensees as provided above.
71.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
71.44 + * Version 2 license, then the option applies only if the new code is
71.45 + * made subject to such option by the copyright holder.
71.46 + */
71.47 +
71.48 +package org.netbeans.modules.python.project2.ui;
71.49 +
71.50 +import java.awt.event.ActionEvent;
71.51 +import java.awt.event.ActionListener;
71.52 +import javax.swing.AbstractAction;
71.53 +import javax.swing.JMenu;
71.54 +import javax.swing.JMenuItem;
71.55 +import javax.swing.JRadioButtonMenuItem;
71.56 +import org.openide.awt.Mnemonics;
71.57 +import org.openide.util.NbBundle;
71.58 +import org.openide.util.actions.Presenter;
71.59 +import static org.netbeans.modules.python.project2.ui.Bundle.*;
71.60 +
71.61 +/**
71.62 + * Popup menu in Projects tab permitting you to change the package view type.
71.63 + *
71.64 + * <p>
71.65 + * <b>This is copied from the corresponding Java action in java.projects</b>
71.66 + * </p>
71.67 + *
71.68 + * @author Jesse Glick
71.69 + */
71.70 +@NbBundle.Messages({"LBL_change_package_type=&View Python Packages as",
71.71 + "ChangePackageViewTypeAction_list=&List",
71.72 + "ChangePackageViewTypeAction_tree=&Tree"})
71.73 +public final class ChangePackageViewTypeAction extends AbstractAction implements Presenter.Popup {
71.74 +
71.75 + public ChangePackageViewTypeAction() {}
71.76 +
71.77 + @Override
71.78 + public void actionPerformed(ActionEvent e) {
71.79 + assert false : e;
71.80 + }
71.81 +
71.82 + @Override
71.83 + public JMenuItem getPopupPresenter() {
71.84 + JMenu menu = new JMenu();
71.85 + Mnemonics.setLocalizedText(menu, LBL_change_package_type());
71.86 + menu.add(createChoice(PythonProjectSettings.TYPE_PACKAGE_VIEW, ChangePackageViewTypeAction_list()));
71.87 + menu.add(createChoice(PythonProjectSettings.TYPE_TREE, ChangePackageViewTypeAction_tree()));
71.88 + return menu;
71.89 + }
71.90 +
71.91 + private JMenuItem createChoice(final int type, String label) {
71.92 + JRadioButtonMenuItem item = new JRadioButtonMenuItem();
71.93 + Mnemonics.setLocalizedText(item, label);
71.94 + item.setSelected(PythonProjectSettings.getPackageViewType() == type);
71.95 + item.addActionListener(new ActionListener() {
71.96 + @Override
71.97 + public void actionPerformed(ActionEvent e) {
71.98 + PythonProjectSettings.setPackageViewType(type);
71.99 + }
71.100 + });
71.101 + return item;
71.102 + }
71.103 +
71.104 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/MainModuleChooser.form Tue Feb 24 01:58:36 2015 -0800
72.3 @@ -0,0 +1,60 @@
72.4 +<?xml version="1.0" encoding="UTF-8" ?>
72.5 +
72.6 +<Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
72.7 + <Properties>
72.8 + <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
72.9 + <Dimension value="[300, 300]"/>
72.10 + </Property>
72.11 + </Properties>
72.12 + <AuxValues>
72.13 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
72.14 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
72.15 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
72.16 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
72.17 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
72.18 + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
72.19 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
72.20 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
72.21 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
72.22 + </AuxValues>
72.23 +
72.24 + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
72.25 + <SubComponents>
72.26 + <Component class="javax.swing.JLabel" name="jLabel1">
72.27 + <Properties>
72.28 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
72.29 + <ComponentRef name="mainModules"/>
72.30 + </Property>
72.31 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
72.32 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/Bundle.properties" key="MainModuleChooser.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
72.33 + </Property>
72.34 + </Properties>
72.35 + <AuxValues>
72.36 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
72.37 + </AuxValues>
72.38 + <Constraints>
72.39 + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
72.40 + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="12" insetsLeft="12" insetsBottom="0" insetsRight="12" anchor="18" weightX="1.0" weightY="0.0"/>
72.41 + </Constraint>
72.42 + </Constraints>
72.43 + </Component>
72.44 + <Container class="javax.swing.JScrollPane" name="jScrollPane1">
72.45 + <Constraints>
72.46 + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
72.47 + <GridBagConstraints gridX="-1" gridY="-1" gridWidth="0" gridHeight="0" fill="1" ipadX="0" ipadY="0" insetsTop="12" insetsLeft="12" insetsBottom="12" insetsRight="12" anchor="10" weightX="1.0" weightY="1.0"/>
72.48 + </Constraint>
72.49 + </Constraints>
72.50 +
72.51 + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
72.52 + <SubComponents>
72.53 + <Component class="javax.swing.JList" name="mainModules">
72.54 + <Properties>
72.55 + <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
72.56 + <Connection code="new DefaultListModel()" type="code"/>
72.57 + </Property>
72.58 + </Properties>
72.59 + </Component>
72.60 + </SubComponents>
72.61 + </Container>
72.62 + </SubComponents>
72.63 +</Form>
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/MainModuleChooser.java Tue Feb 24 01:58:36 2015 -0800
73.3 @@ -0,0 +1,137 @@
73.4 +/*
73.5 + * MainClassChooser.java
73.6 + *
73.7 + * Created on August 22, 2008, 6:07 PM
73.8 + */
73.9 +
73.10 +package org.netbeans.modules.python.project2.ui;
73.11 +
73.12 +import java.util.Enumeration;
73.13 +import java.util.LinkedList;
73.14 +import java.util.List;
73.15 +import javax.swing.DefaultListModel;
73.16 +import javax.swing.JButton;
73.17 +import javax.swing.SwingUtilities;
73.18 +import org.netbeans.api.project.ProjectUtils;
73.19 +import org.netbeans.api.project.SourceGroup;
73.20 +import org.netbeans.api.project.Sources;
73.21 +import org.netbeans.modules.python.api.PythonMIMEResolver;
73.22 +import org.netbeans.modules.python.project2.PythonProject2;
73.23 +import org.openide.filesystems.FileObject;
73.24 +import org.openide.filesystems.FileUtil;
73.25 +import org.openide.util.NbBundle;
73.26 +import org.openide.util.RequestProcessor;
73.27 +
73.28 +/**
73.29 + *
73.30 + * @author Tomas Zezula
73.31 + */
73.32 +@NbBundle.Messages({"TXT_PleaseWait=Please Wait..."})
73.33 +final class MainModuleChooser extends javax.swing.JPanel {
73.34 +
73.35 + private final PythonProject2 project;
73.36 + private final JButton okButton;
73.37 + private final static RequestProcessor RP = new RequestProcessor("MainModuleChooser"); //NOI18N
73.38 +
73.39 + /** Creates new form MainClassChooser */
73.40 + MainModuleChooser (final PythonProject2 project, final JButton okButton) {
73.41 + assert project != null;
73.42 + assert okButton != null;
73.43 + initComponents();
73.44 + this.project = project;
73.45 + this.okButton = okButton;
73.46 + this.okButton.setEnabled(false);
73.47 + ((DefaultListModel)this.mainModules.getModel()).addElement(NbBundle.getMessage(MainModuleChooser.class, "TXT_PleaseWait"));
73.48 + RP.post(new Runnable() {
73.49 + @Override
73.50 + public void run() {
73.51 + initData();
73.52 + }
73.53 + });
73.54 + }
73.55 +
73.56 + public String getMainModule () {
73.57 + return (String) mainModules.getSelectedValue();
73.58 + }
73.59 +
73.60 +
73.61 + private void initData () {
73.62 + final List<String> data = new LinkedList<>();
73.63 + Sources sources = ProjectUtils.getSources(project);
73.64 + for (SourceGroup sourceGroup : sources.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON)) {
73.65 + final Enumeration<? extends FileObject> fos = sourceGroup.getRootFolder().getChildren(true);
73.66 + while (fos.hasMoreElements()) {
73.67 + final FileObject fo = fos.nextElement();
73.68 + if (isPython (fo)) {
73.69 + data.add(FileUtil.getRelativePath(sourceGroup.getRootFolder(), fo));
73.70 + }
73.71 + }
73.72 + }
73.73 + SwingUtilities.invokeLater(new Runnable() {
73.74 + @Override
73.75 + public void run() {
73.76 + DefaultListModel lm = (DefaultListModel)mainModules.getModel();
73.77 + lm.clear();
73.78 + for (String s : data) {
73.79 + lm.addElement(s);
73.80 + }
73.81 + okButton.setEnabled(true);
73.82 + }
73.83 + });
73.84 + }
73.85 +
73.86 + private static boolean isPython (final FileObject fo) {
73.87 + if (fo.isFolder() || !fo.isValid() || fo.isVirtual()) {
73.88 + return false;
73.89 + }
73.90 + return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(FileUtil.getMIMEType(fo));
73.91 + }
73.92 +
73.93 + /** This method is called from within the constructor to
73.94 + * initialize the form.
73.95 + * WARNING: Do NOT modify this code. The content of this method is
73.96 + * always regenerated by the Form Editor.
73.97 + */
73.98 + @SuppressWarnings("unchecked")
73.99 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
73.100 + private void initComponents() {
73.101 + java.awt.GridBagConstraints gridBagConstraints;
73.102 +
73.103 + jLabel1 = new javax.swing.JLabel();
73.104 + jScrollPane1 = new javax.swing.JScrollPane();
73.105 + mainModules = new javax.swing.JList();
73.106 +
73.107 + setPreferredSize(new java.awt.Dimension(300, 300));
73.108 + setLayout(new java.awt.GridBagLayout());
73.109 +
73.110 + jLabel1.setLabelFor(mainModules);
73.111 + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MainModuleChooser.class, "MainModuleChooser.jLabel1.text")); // NOI18N
73.112 + gridBagConstraints = new java.awt.GridBagConstraints();
73.113 + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
73.114 + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
73.115 + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
73.116 + gridBagConstraints.weightx = 1.0;
73.117 + gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 12);
73.118 + add(jLabel1, gridBagConstraints);
73.119 +
73.120 + mainModules.setModel(new DefaultListModel());
73.121 + jScrollPane1.setViewportView(mainModules);
73.122 +
73.123 + gridBagConstraints = new java.awt.GridBagConstraints();
73.124 + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
73.125 + gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
73.126 + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
73.127 + gridBagConstraints.weightx = 1.0;
73.128 + gridBagConstraints.weighty = 1.0;
73.129 + gridBagConstraints.insets = new java.awt.Insets(12, 12, 12, 12);
73.130 + add(jScrollPane1, gridBagConstraints);
73.131 + }// </editor-fold>//GEN-END:initComponents
73.132 +
73.133 +
73.134 + // Variables declaration - do not modify//GEN-BEGIN:variables
73.135 + private javax.swing.JLabel jLabel1;
73.136 + private javax.swing.JScrollPane jScrollPane1;
73.137 + private javax.swing.JList mainModules;
73.138 + // End of variables declaration//GEN-END:variables
73.139 +
73.140 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/PackageDisplayUtils.java Tue Feb 24 01:58:36 2015 -0800
74.3 @@ -0,0 +1,222 @@
74.4 +/*
74.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
74.6 + *
74.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
74.8 + *
74.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
74.10 + * Other names may be trademarks of their respective owners.
74.11 + *
74.12 + * The contents of this file are subject to the terms of either the GNU
74.13 + * General Public License Version 2 only ("GPL") or the Common
74.14 + * Development and Distribution License("CDDL") (collectively, the
74.15 + * "License"). You may not use this file except in compliance with the
74.16 + * License. You can obtain a copy of the License at
74.17 + * http://www.netbeans.org/cddl-gplv2.html
74.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
74.19 + * specific language governing permissions and limitations under the
74.20 + * License. When distributing the software, include this License Header
74.21 + * Notice in each file and include the License file at
74.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
74.23 + * particular file as subject to the "Classpath" exception as provided
74.24 + * by Oracle in the GPL Version 2 section of the License file that
74.25 + * accompanied this code. If applicable, add the following below the
74.26 + * License Header, with the fields enclosed by brackets [] replaced by
74.27 + * your own identifying information:
74.28 + * "Portions Copyrighted [year] [name of copyright owner]"
74.29 + *
74.30 + * Contributor(s):
74.31 + *
74.32 + * The Original Software is NetBeans. The Initial Developer of the Original
74.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
74.34 + * Microsystems, Inc. All Rights Reserved.
74.35 + *
74.36 + * If you wish your version of this file to be governed by only the CDDL
74.37 + * or only the GPL Version 2, indicate your decision by adding
74.38 + * "[Contributor] elects to include this software in this distribution
74.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
74.40 + * single choice of license, a recipient has the option to distribute
74.41 + * your version of this file under either the CDDL, the GPL Version 2 or
74.42 + * to extend the choice of license to its licensees as provided above.
74.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
74.44 + * Version 2 license, then the option applies only if the new code is
74.45 + * made subject to such option by the copyright holder.
74.46 + */
74.47 +
74.48 +package org.netbeans.modules.python.project2.ui;
74.49 +
74.50 +import java.awt.Image;
74.51 +//import org.netbeans.api.java.queries.AccessibilityQuery;
74.52 +import org.netbeans.api.queries.VisibilityQuery;
74.53 +import org.openide.filesystems.FileObject;
74.54 +import org.openide.util.ImageUtilities;
74.55 +import org.openide.util.NbBundle;
74.56 +
74.57 +// XXX needs unit test
74.58 +
74.59 +/**
74.60 + * Provides display name and icon utilities for
74.61 + * {@link PackageViewChildren.PackageNode} and {@link PackageListView.PackageItem}.
74.62 + *
74.63 + * <p>
74.64 + * <b>This is copied from the corresponding Java action in java.projects</b>
74.65 + * </p>
74.66 + *
74.67 + *
74.68 + * @author Jesse Glick
74.69 + */
74.70 +@NbBundle.Messages({"#LBL_DefaultPackage=<default package>",
74.71 + "LBL_DefaultPackage=<Top Level>",
74.72 + "# {0} - full package name",
74.73 + "LBL_package= PythonPackage ({0})",
74.74 + "# {0} - full package name",
74.75 + "LBL_public_package=Exported Python Source Package ({0})",
74.76 + "# {0} - full package name",
74.77 + "LBL_private_package=Private Python Source Package ({0})"})
74.78 +public final class PackageDisplayUtils {
74.79 +
74.80 + private PackageDisplayUtils() {}
74.81 +
74.82 + private static final Image PACKAGE = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/package.gif"); // NOI18N
74.83 + private static final Image PACKAGE_EMPTY = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/packageEmpty.gif"); // NOI18N
74.84 + private static final Image PACKAGE_PRIVATE = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/packagePrivate.gif"); // NOI18N
74.85 + private static final Image PACKAGE_PUBLIC = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/packagePublic.gif"); // NOI18N
74.86 +
74.87 + /**
74.88 + * Find the proper display label for a package.
74.89 + * @param pkg the actual folder
74.90 + * @param pkgname the dot-separated package name (<code>""</code> for default package)
74.91 + * @return an appropriate display label for it
74.92 + */
74.93 + public static String getDisplayLabel(String pkgname) {
74.94 + return computePackageName(pkgname);
74.95 + }
74.96 +
74.97 + /**
74.98 + * Find the proper tool tip for a package.
74.99 + * May have more info than the display label.
74.100 + * @param pkg the actual folder
74.101 + * @param pkgname the dot-separated package name (<code>""</code> for default package)
74.102 + * @return an appropriate display label for it
74.103 + */
74.104 + public static String getToolTip(FileObject pkg, String pkgname) {
74.105 + String pkglabel = computePackageName(pkgname);
74.106 +// Boolean b = AccessibilityQuery.isPubliclyAccessible(pkg);
74.107 +// if (b != null) {
74.108 +// if (b.booleanValue()) {
74.109 +// return NbBundle.getMessage(PackageDisplayUtils.class, "LBL_public_package", pkglabel);
74.110 +// } else {
74.111 +// return NbBundle.getMessage(PackageDisplayUtils.class, "LBL_private_package", pkglabel);
74.112 +// }
74.113 +// } else {
74.114 + return NbBundle.getMessage(PackageDisplayUtils.class, "LBL_package", pkglabel);
74.115 +// }
74.116 + }
74.117 +
74.118 + /**
74.119 + * Get package name.
74.120 + * Handles default package specially.
74.121 + */
74.122 + private static String computePackageName(String pkgname) {
74.123 + if (pkgname.length() == 0) {
74.124 + return NbBundle.getMessage(PackageDisplayUtils.class, "LBL_DefaultPackage"); // NOI18N
74.125 + } else {
74.126 + return pkgname;
74.127 + }
74.128 + }
74.129 +
74.130 +
74.131 +
74.132 + /**
74.133 + * Find the proper display icon for a package.
74.134 + * @param pkg the actual folder
74.135 + * @param pkgname the dot-separated package name (<code>""</code> for default package)
74.136 + * @return an appropriate display icon for it
74.137 + */
74.138 + public static Image getIcon(FileObject pkg, String pkgname) {
74.139 + return getIcon( pkg, pkgname, isEmpty(pkg) );
74.140 + }
74.141 +
74.142 + /** Performance optimization if the the isEmpty status is already known.
74.143 + *
74.144 + */
74.145 + public static Image getIcon(FileObject pkg, String pkgname, boolean empty ) {
74.146 + if ( empty ) {
74.147 + return PACKAGE_EMPTY;
74.148 + } else {
74.149 +// Boolean b = pkg.isValid() ? AccessibilityQuery.isPubliclyAccessible(pkg) : null;
74.150 +// if (b != null) {
74.151 +// if (b.booleanValue()) {
74.152 +// return PACKAGE_PUBLIC;
74.153 +// } else {
74.154 +// return PACKAGE_PRIVATE;
74.155 +// }
74.156 +// } else {
74.157 + return PACKAGE;
74.158 +// }
74.159 + }
74.160 + }
74.161 +
74.162 +
74.163 + /**
74.164 + * Check whether a package is empty (devoid of files except for subpackages).
74.165 + */
74.166 + public static boolean isEmpty( FileObject fo ) {
74.167 + return isEmpty (fo, true, false );
74.168 + }
74.169 +
74.170 + /**
74.171 + * Check whether a package is empty (devoid of files except for subpackages).
74.172 + * @param recurse specifies whether to check if subpackages are empty too.
74.173 + * @param initIsEmpty If true, don't consider __init__.py presence
74.174 + */
74.175 + public static boolean isEmpty( FileObject fo, boolean recurse, boolean initIsEmpty ) {
74.176 + FileObject[] kids = fo.getChildren();
74.177 + for( int i = 0; i < kids.length; i++ ) {
74.178 + final FileObject kid = kids[i];
74.179 + // Package init files don't count unless they have contents (or are pyc files)
74.180 + if (initIsEmpty && kid.getName().equals("__init__")) { // NOI18N
74.181 + if ("pyc".equals(kid.getExt()) || "pyo".equals(kid.getExt()) || kid.getSize() == 0) { // NOI18N
74.182 + continue;
74.183 + }
74.184 + }
74.185 + // XXX consider using group.contains() here
74.186 + if ( !kid.isFolder() && VisibilityQuery.getDefault().isVisible( kid) ) {
74.187 + return false;
74.188 + }
74.189 + else if (recurse && VisibilityQuery.getDefault().isVisible( kid) && !isEmpty(kid)) {
74.190 + return false;
74.191 + }
74.192 + }
74.193 + return true;
74.194 + }
74.195 +
74.196 + /**
74.197 + * Check whether a package should be displayed.
74.198 + * It should be displayed if {@link VisibilityQuery} says it should be,
74.199 + * and it is either completely empty, or contains files (as opposed to
74.200 + * containing some subpackages but no files).
74.201 + */
74.202 +// public static boolean isSignificant(FileObject pkg) throws IllegalArgumentException {
74.203 +// if (!pkg.isFolder()) {
74.204 +// throw new IllegalArgumentException("Not a folder"); // NOI18N
74.205 +// }
74.206 +// // XXX consider using group.contains() here
74.207 +// if (!VisibilityQuery.getDefault().isVisible(pkg)) {
74.208 +// return false;
74.209 +// }
74.210 +// FileObject[] kids = pkg.getChildren();
74.211 +// boolean subpackages = false;
74.212 +// for (int i = 0; i < kids.length; i++) {
74.213 +// if (!VisibilityQuery.getDefault().isVisible(kids[i])) {
74.214 +// continue;
74.215 +// }
74.216 +// if (kids[i].isData()) {
74.217 +// return true;
74.218 +// } else {
74.219 +// subpackages = true;
74.220 +// }
74.221 +// }
74.222 +// return !subpackages;
74.223 +// }
74.224 +
74.225 +}
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/PackageRootNode.java Tue Feb 24 01:58:36 2015 -0800
75.3 @@ -0,0 +1,449 @@
75.4 +/*
75.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75.6 + *
75.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
75.8 + *
75.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
75.10 + * Other names may be trademarks of their respective owners.
75.11 + *
75.12 + * The contents of this file are subject to the terms of either the GNU
75.13 + * General Public License Version 2 only ("GPL") or the Common
75.14 + * Development and Distribution License("CDDL") (collectively, the
75.15 + * "License"). You may not use this file except in compliance with the
75.16 + * License. You can obtain a copy of the License at
75.17 + * http://www.netbeans.org/cddl-gplv2.html
75.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
75.19 + * specific language governing permissions and limitations under the
75.20 + * License. When distributing the software, include this License Header
75.21 + * Notice in each file and include the License file at
75.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
75.23 + * particular file as subject to the "Classpath" exception as provided
75.24 + * by Oracle in the GPL Version 2 section of the License file that
75.25 + * accompanied this code. If applicable, add the following below the
75.26 + * License Header, with the fields enclosed by brackets [] replaced by
75.27 + * your own identifying information:
75.28 + * "Portions Copyrighted [year] [name of copyright owner]"
75.29 + *
75.30 + * Contributor(s):
75.31 + *
75.32 + * The Original Software is NetBeans. The Initial Developer of the Original
75.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
75.34 + * Microsystems, Inc. All Rights Reserved.
75.35 + *
75.36 + * If you wish your version of this file to be governed by only the CDDL
75.37 + * or only the GPL Version 2, indicate your decision by adding
75.38 + * "[Contributor] elects to include this software in this distribution
75.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
75.40 + * single choice of license, a recipient has the option to distribute
75.41 + * your version of this file under either the CDDL, the GPL Version 2 or
75.42 + * to extend the choice of license to its licensees as provided above.
75.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
75.44 + * Version 2 license, then the option applies only if the new code is
75.45 + * made subject to such option by the copyright holder.
75.46 + */
75.47 +
75.48 +package org.netbeans.modules.python.project2.ui;
75.49 +
75.50 +import java.awt.Image;
75.51 +import java.awt.datatransfer.DataFlavor;
75.52 +import java.awt.datatransfer.Transferable;
75.53 +import java.awt.datatransfer.UnsupportedFlavorException;
75.54 +import java.io.IOException;
75.55 +import java.util.ArrayList;
75.56 +import java.util.Arrays;
75.57 +import java.util.Collections;
75.58 +import java.util.Iterator;
75.59 +import java.util.List;
75.60 +import java.util.Set;
75.61 +import javax.swing.Action;
75.62 +import javax.swing.Icon;
75.63 +import org.netbeans.api.project.SourceGroup;
75.64 +import org.netbeans.spi.project.ui.support.CommonProjectActions;
75.65 +import org.openide.ErrorManager;
75.66 +import org.openide.actions.FileSystemAction;
75.67 +import org.openide.actions.FindAction;
75.68 +import org.openide.actions.PasteAction;
75.69 +import org.openide.actions.ToolsAction;
75.70 +import org.openide.filesystems.FileObject;
75.71 +import org.openide.filesystems.FileStateInvalidException;
75.72 +import org.openide.filesystems.FileStatusEvent;
75.73 +import org.openide.filesystems.FileStatusListener;
75.74 +import org.openide.filesystems.FileSystem;
75.75 +import org.openide.filesystems.FileUtil;
75.76 +import org.openide.loaders.DataFolder;
75.77 +import org.openide.loaders.DataObject;
75.78 +import org.openide.nodes.AbstractNode;
75.79 +import org.openide.nodes.Children;
75.80 +import org.openide.nodes.Node;
75.81 +import org.openide.nodes.Node.PropertySet;
75.82 +import org.openide.nodes.NodeNotFoundException;
75.83 +import org.openide.nodes.NodeOp;
75.84 +import org.openide.nodes.PropertySupport;
75.85 +import org.openide.nodes.Sheet;
75.86 +import org.openide.util.ImageUtilities;
75.87 +import org.openide.util.Lookup;
75.88 +import org.openide.util.NbBundle;
75.89 +import org.openide.util.RequestProcessor;
75.90 +import org.openide.util.actions.SystemAction;
75.91 +import org.openide.util.datatransfer.ExTransferable;
75.92 +import org.openide.util.datatransfer.MultiTransferObject;
75.93 +import org.openide.util.datatransfer.PasteType;
75.94 +import org.openide.util.lookup.AbstractLookup;
75.95 +import org.openide.util.lookup.InstanceContent;
75.96 +import org.openide.util.lookup.Lookups;
75.97 +import org.openide.util.lookup.ProxyLookup;
75.98 +//import org.openidex.search.SearchInfo;
75.99 +//import org.openidex.search.SearchInfoFactory;
75.100 +
75.101 +/** Node displaying a packages in given SourceGroup
75.102 + *
75.103 + * <p>
75.104 + * <b>This is copied from the corresponding Java action in java.projects</b>
75.105 + * </p>
75.106 + *
75.107 + * @author Petr Hrebejk
75.108 + */
75.109 +final class PackageRootNode extends AbstractNode implements Runnable, FileStatusListener {
75.110 +
75.111 + static Image PACKAGE_BADGE = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/packageBadge.gif"); // NOI18N
75.112 +
75.113 + private static Action actions[];
75.114 +
75.115 + private SourceGroup group;
75.116 +
75.117 + private final FileObject file;
75.118 + private final Set<FileObject> files;
75.119 + private FileStatusListener fileSystemListener;
75.120 + private static final RequestProcessor RP = new RequestProcessor(PackageRootNode.class);
75.121 + private RequestProcessor.Task task;
75.122 + private volatile boolean iconChange;
75.123 + private volatile boolean nameChange;
75.124 +
75.125 + PackageRootNode( SourceGroup group ) {
75.126 + this( group, new InstanceContent() );
75.127 + }
75.128 +
75.129 + private PackageRootNode( SourceGroup group, InstanceContent ic ) {
75.130 + super( new PackageViewChildren(group),
75.131 + new ProxyLookup(createLookup(group), new AbstractLookup(ic)));
75.132 +// ic.add(alwaysSearchableSearchInfo(SearchInfoFactory.createSearchInfoBySubnodes(this)));
75.133 + this.group = group;
75.134 + file = group.getRootFolder();
75.135 + files = Collections.singleton(file);
75.136 + try {
75.137 + FileSystem fs = file.getFileSystem();
75.138 + fileSystemListener = FileUtil.weakFileStatusListener(this, fs);
75.139 + fs.addFileStatusListener(fileSystemListener);
75.140 + } catch (FileStateInvalidException e) {
75.141 + ErrorManager err = ErrorManager.getDefault();
75.142 + err.annotate(e, "Can not get " + file + " filesystem, ignoring..."); // NO18N
75.143 + err.notify(ErrorManager.INFORMATIONAL, e);
75.144 + }
75.145 + setName( group.getName() );
75.146 + setDisplayName( group.getDisplayName() );
75.147 + // setIconBase("org/netbeans/modules/java/j2seproject/ui/resources/packageRoot");
75.148 + }
75.149 +
75.150 + public @Override Image getIcon(int type) {
75.151 + return computeIcon( false, type );
75.152 + }
75.153 +
75.154 + public @Override Image getOpenedIcon(int type) {
75.155 + return computeIcon( true, type );
75.156 + }
75.157 +
75.158 + public @Override String getDisplayName() {
75.159 + String s = super.getDisplayName ();
75.160 +
75.161 + try {
75.162 + s = file.getFileSystem ().getStatus ().annotateName (s, files);
75.163 + } catch (FileStateInvalidException e) {
75.164 + ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
75.165 + }
75.166 +
75.167 + return s;
75.168 + }
75.169 +
75.170 + public @Override String getHtmlDisplayName() {
75.171 + try {
75.172 + FileSystem.Status stat = file.getFileSystem().getStatus();
75.173 + if (stat instanceof FileSystem.HtmlStatus) {
75.174 + FileSystem.HtmlStatus hstat = (FileSystem.HtmlStatus) stat;
75.175 +
75.176 + String result = hstat.annotateNameHtml (
75.177 + super.getDisplayName(), files);
75.178 +
75.179 + //Make sure the super string was really modified
75.180 + if (!super.getDisplayName().equals(result)) {
75.181 + return result;
75.182 + }
75.183 + }
75.184 + } catch (FileStateInvalidException e) {
75.185 + ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
75.186 + }
75.187 + return super.getHtmlDisplayName();
75.188 + }
75.189 +
75.190 + @Override
75.191 + public void run() {
75.192 + if (iconChange) {
75.193 + fireIconChange();
75.194 + fireOpenedIconChange();
75.195 + iconChange = false;
75.196 + }
75.197 + if (nameChange) {
75.198 + fireDisplayNameChange(null, null);
75.199 + nameChange = false;
75.200 + }
75.201 + }
75.202 +
75.203 + @Override
75.204 + public void annotationChanged(FileStatusEvent event) {
75.205 + if (task == null) {
75.206 + task = RP.create(this);
75.207 + }
75.208 +
75.209 + if ((iconChange == false && event.isIconChange()) || (nameChange == false && event.isNameChange())) {
75.210 + if (event.hasChanged(file)) {
75.211 + iconChange |= event.isIconChange();
75.212 + nameChange |= event.isNameChange();
75.213 + }
75.214 + }
75.215 +
75.216 + task.schedule(50); // batch by 50 ms
75.217 + }
75.218 +
75.219 + public @Override Action[] getActions(boolean context) {
75.220 + if ( actions == null ) {
75.221 + actions = new Action[] {
75.222 + CommonProjectActions.newFileAction(),
75.223 + null,
75.224 + SystemAction.get( FileSystemAction.class ),
75.225 + null,
75.226 + SystemAction.get( FindAction.class ),
75.227 + null,
75.228 + SystemAction.get( PasteAction.class ),
75.229 + null,
75.230 + SystemAction.get( ToolsAction.class ),
75.231 + };
75.232 + }
75.233 + return actions;
75.234 + }
75.235 +
75.236 + // Show reasonable properties of the DataFolder,
75.237 + //it shows the sorting names as rw property, the name as ro property and the path to root as ro property
75.238 + public @Override PropertySet[] getPropertySets() {
75.239 + PropertySet[] properties = getDataFolderNodeDelegate().getPropertySets();
75.240 + for (int i=0; i< properties.length; i++) {
75.241 + if (Sheet.PROPERTIES.equals(properties[i].getName())) {
75.242 + //Replace the Sheet.PROPERTIES by the new one
75.243 + //having the ro name property and ro path property
75.244 + properties[i] = Sheet.createPropertiesSet();
75.245 + ((Sheet.Set) properties[i]).put(new PropertySupport.ReadOnly<String>(DataObject.PROP_NAME, String.class,
75.246 + NbBundle.getMessage(PackageRootNode.class,"PROP_name"), NbBundle.getMessage(PackageRootNode.class,"HINT_name")) {
75.247 + @Override
75.248 + public String getValue() {
75.249 + return PackageRootNode.this.getDisplayName();
75.250 + }
75.251 + });
75.252 + ((Sheet.Set) properties[i]).put(new PropertySupport.ReadOnly<String>("ROOT_PATH", String.class, //NOI18N
75.253 +NbBundle.getMessage(PackageRootNode.class,"PROP_rootpath"), NbBundle.getMessage(PackageRootNode.class,"HINT_rootpath")) {
75.254 + @Override
75.255 + public String getValue() {
75.256 + return FileUtil.getFileDisplayName(PackageRootNode.this.file);
75.257 + }
75.258 + });
75.259 + }
75.260 + }
75.261 + return properties;
75.262 + }
75.263 +
75.264 + // XXX Paste types - probably not very nice
75.265 + public @Override void createPasteTypes(Transferable t, List<PasteType> list) {
75.266 + if (t.isDataFlavorSupported(ExTransferable.multiFlavor)) {
75.267 + try {
75.268 + MultiTransferObject mto = (MultiTransferObject) t.getTransferData(ExTransferable.multiFlavor);
75.269 + List<PackageViewChildren.PackageNode> l = new ArrayList<>();
75.270 + boolean isPackageFlavor = false;
75.271 + boolean hasTheSameRoot = false;
75.272 + int op = -1;
75.273 + for (int i=0; i < mto.getCount(); i++) {
75.274 + Transferable pt = mto.getTransferableAt(i);
75.275 + DataFlavor[] flavors = mto.getTransferDataFlavors(i);
75.276 + for (int j=0; j< flavors.length; j++) {
75.277 + if (PackageViewChildren.SUBTYPE.equals(flavors[j].getSubType ()) &&
75.278 + PackageViewChildren.PRIMARY_TYPE.equals(flavors[j].getPrimaryType ())) {
75.279 + if (op == -1) {
75.280 + op = Integer.valueOf (flavors[j].getParameter (PackageViewChildren.MASK)).intValue ();
75.281 + }
75.282 + PackageViewChildren.PackageNode pkgNode = (PackageViewChildren.PackageNode) pt.getTransferData(flavors[j]);
75.283 + if ( !((PackageViewChildren)getChildren()).getRoot().equals( pkgNode.getRoot() ) ) {
75.284 + l.add(pkgNode);
75.285 + }
75.286 + else {
75.287 + hasTheSameRoot = true;
75.288 + }
75.289 + isPackageFlavor = true;
75.290 + }
75.291 + }
75.292 + }
75.293 + if (isPackageFlavor && !hasTheSameRoot) {
75.294 + list.add(new PackageViewChildren.PackagePasteType(this.group.getRootFolder(),
75.295 + l.toArray(new PackageViewChildren.PackageNode[l.size()]),
75.296 + op));
75.297 + }
75.298 + else if (!isPackageFlavor) {
75.299 + list.addAll( Arrays.asList( getDataFolderNodeDelegate().getPasteTypes( t ) ) );
75.300 + }
75.301 + } catch (UnsupportedFlavorException | IOException e) {
75.302 + ErrorManager.getDefault().notify(e);
75.303 + }
75.304 + }
75.305 + else {
75.306 + DataFlavor[] flavors = t.getTransferDataFlavors();
75.307 + FileObject root = this.group.getRootFolder();
75.308 + boolean isPackageFlavor = false;
75.309 + if (root!= null && root.canWrite()) {
75.310 + for (DataFlavor flavor : flavors) {
75.311 + if (PackageViewChildren.SUBTYPE.equals(flavor.getSubType ()) &&
75.312 + PackageViewChildren.PRIMARY_TYPE.equals(flavor.getPrimaryType ())) {
75.313 + isPackageFlavor = true;
75.314 + try {
75.315 + int op = Integer.parseInt(flavor.getParameter(PackageViewChildren.MASK));
75.316 + PackageViewChildren.PackageNode pkgNode = (PackageViewChildren.PackageNode) t.getTransferData(flavor);
75.317 + if ( !((PackageViewChildren)getChildren()).getRoot().equals( pkgNode.getRoot() ) ) {
75.318 + list.add(new PackageViewChildren.PackagePasteType (root, new PackageViewChildren.PackageNode[] {pkgNode}, op));
75.319 + }
75.320 + } catch (IOException | UnsupportedFlavorException ioe) {
75.321 + ErrorManager.getDefault().notify(ioe);
75.322 + }
75.323 + }
75.324 + }
75.325 + }
75.326 + if (!isPackageFlavor) {
75.327 + list.addAll( Arrays.asList( getDataFolderNodeDelegate().getPasteTypes( t ) ) );
75.328 + }
75.329 + }
75.330 + }
75.331 +
75.332 + @Override
75.333 + public PasteType getDropType(Transferable t, int action, int index) {
75.334 + PasteType pasteType = super.getDropType(t, action, index);
75.335 + //The pasteType can be:
75.336 + // 1) PackagePasteType - the t.flavor is package flavor
75.337 + // 2) null or DataPasteType - the t.flavor in not package flavor
75.338 + if (pasteType instanceof PackageViewChildren.PackagePasteType) {
75.339 + ((PackageViewChildren.PackagePasteType)pasteType).setOperation (action);
75.340 + }
75.341 + return pasteType;
75.342 + }
75.343 +
75.344 + // Private methods ---------------------------------------------------------
75.345 +
75.346 + private Node getDataFolderNodeDelegate() {
75.347 + DataFolder df = getLookup().lookup(DataFolder.class);
75.348 + try {
75.349 + if (df.isValid()) {
75.350 + return df.getNodeDelegate();
75.351 + }
75.352 + } catch (IllegalStateException e) {
75.353 + //The data systems API is not thread save,
75.354 + //the DataObject may become invalid after isValid call and before
75.355 + //getNodeDelegate call, we have to catch the ISE. When the DataObject
75.356 + //is valid - other cause rethrow it otherwise return leaf node.
75.357 + //todo: The DataObject.getNodedelegate should throw specialized exception type.
75.358 + if (df.isValid()) {
75.359 + throw e;
75.360 + }
75.361 + }
75.362 + return new AbstractNode(Children.LEAF);
75.363 + }
75.364 +
75.365 + private Image computeIcon( boolean opened, int type ) {
75.366 + Image image;
75.367 + Icon icon = group.getIcon( opened );
75.368 +
75.369 + if ( icon == null ) {
75.370 + image = opened ? getDataFolderNodeDelegate().getOpenedIcon( type ) :
75.371 + getDataFolderNodeDelegate().getIcon( type );
75.372 + image = ImageUtilities.mergeImages(image, PACKAGE_BADGE, 7, 7);
75.373 + }
75.374 + else {
75.375 + image = ImageUtilities.icon2Image(icon);
75.376 + }
75.377 +
75.378 + return image;
75.379 + }
75.380 +
75.381 + private static Lookup createLookup( SourceGroup group ) {
75.382 + // XXX Remove DataFolder when paste, find and refresh are reimplemented
75.383 + FileObject rootFolder = group.getRootFolder();
75.384 + DataFolder dataFolder = DataFolder.findFolder( rootFolder );
75.385 + return Lookups.fixed(dataFolder, new PathFinder(group));
75.386 + }
75.387 +
75.388 + /** If contained in the lookup can perform the search for a node
75.389 + */
75.390 + public static class PathFinder {
75.391 +
75.392 + private SourceGroup group;
75.393 +
75.394 + public PathFinder( SourceGroup group ) {
75.395 + this.group = group;
75.396 + }
75.397 +
75.398 + public Node findPath( Node root, Object object ) {
75.399 + FileObject fo;
75.400 + if (object instanceof FileObject) {
75.401 + fo = (FileObject) object;
75.402 + } else if (object instanceof DataObject) {
75.403 + fo = ((DataObject) object).getPrimaryFile();
75.404 + } else {
75.405 + return null;
75.406 + }
75.407 +
75.408 + FileObject groupRoot = group.getRootFolder();
75.409 + if ( FileUtil.isParentOf( groupRoot, fo ) /* && group.contains( fo ) */ ) {
75.410 + // The group contains the object
75.411 +
75.412 + String relPath = FileUtil.getRelativePath( groupRoot, fo.isFolder() ? fo : fo.getParent() );
75.413 +
75.414 + String[] path = new String[] { relPath.replace( '/', '.' ) };
75.415 + try {
75.416 + Node packageNode = NodeOp.findPath( root, path );
75.417 + if (fo.isFolder()) {
75.418 + return packageNode;
75.419 + } else {
75.420 + for (Node child : packageNode.getChildren().getNodes(true)) {
75.421 + DataObject dobj = child.getLookup().lookup(DataObject.class);
75.422 + if (dobj != null && dobj.getPrimaryFile().getNameExt().equals(fo.getNameExt())) {
75.423 + return child;
75.424 + }
75.425 + }
75.426 + }
75.427 + }
75.428 + catch ( NodeNotFoundException e ) {
75.429 + // did not manage to find it after all... why?
75.430 + return null;
75.431 + }
75.432 + }
75.433 + else if ( groupRoot.equals( fo ) ) {
75.434 + // First try to find default package
75.435 + try {
75.436 + return NodeOp.findPath( root, new String[] { "" } ); // NOI18N
75.437 + }
75.438 + catch ( NodeNotFoundException e ) {
75.439 + // If it does not exists return this node
75.440 + }
75.441 + return root;
75.442 + }
75.443 +
75.444 + return null;
75.445 + }
75.446 +
75.447 + public @Override String toString() {
75.448 + return "PathFinder[" + group + "]"; // NOI18N
75.449 + }
75.450 +
75.451 + }
75.452 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/PackageView.java Tue Feb 24 01:58:36 2015 -0800
76.3 @@ -0,0 +1,403 @@
76.4 +/*
76.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
76.6 + *
76.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
76.8 + *
76.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
76.10 + * Other names may be trademarks of their respective owners.
76.11 + *
76.12 + * The contents of this file are subject to the terms of either the GNU
76.13 + * General Public License Version 2 only ("GPL") or the Common
76.14 + * Development and Distribution License("CDDL") (collectively, the
76.15 + * "License"). You may not use this file except in compliance with the
76.16 + * License. You can obtain a copy of the License at
76.17 + * http://www.netbeans.org/cddl-gplv2.html
76.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
76.19 + * specific language governing permissions and limitations under the
76.20 + * License. When distributing the software, include this License Header
76.21 + * Notice in each file and include the License file at
76.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
76.23 + * particular file as subject to the "Classpath" exception as provided
76.24 + * by Oracle in the GPL Version 2 section of the License file that
76.25 + * accompanied this code. If applicable, add the following below the
76.26 + * License Header, with the fields enclosed by brackets [] replaced by
76.27 + * your own identifying information:
76.28 + * "Portions Copyrighted [year] [name of copyright owner]"
76.29 + *
76.30 + * Contributor(s):
76.31 + *
76.32 + * The Original Software is NetBeans. The Initial Developer of the Original
76.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
76.34 + * Microsystems, Inc. All Rights Reserved.
76.35 + *
76.36 + * If you wish your version of this file to be governed by only the CDDL
76.37 + * or only the GPL Version 2, indicate your decision by adding
76.38 + * "[Contributor] elects to include this software in this distribution
76.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
76.40 + * single choice of license, a recipient has the option to distribute
76.41 + * your version of this file under either the CDDL, the GPL Version 2 or
76.42 + * to extend the choice of license to its licensees as provided above.
76.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
76.44 + * Version 2 license, then the option applies only if the new code is
76.45 + * made subject to such option by the copyright holder.
76.46 + */
76.47 +
76.48 +package org.netbeans.modules.python.project2.ui;
76.49 +
76.50 +import java.awt.Component;
76.51 +import java.awt.EventQueue;
76.52 +import java.awt.Image;
76.53 +import java.beans.PropertyChangeEvent;
76.54 +import java.beans.PropertyChangeListener;
76.55 +import java.util.ArrayList;
76.56 +import java.util.Collection;
76.57 +import java.util.IdentityHashMap;
76.58 +import java.util.List;
76.59 +import java.util.Map;
76.60 +import java.util.SortedSet;
76.61 +import java.util.TreeSet;
76.62 +import javax.swing.ComboBoxModel;
76.63 +import javax.swing.DefaultComboBoxModel;
76.64 +import javax.swing.Icon;
76.65 +import javax.swing.ImageIcon;
76.66 +import javax.swing.JLabel;
76.67 +import javax.swing.JList;
76.68 +import javax.swing.ListCellRenderer;
76.69 +import javax.swing.plaf.UIResource;
76.70 +import org.netbeans.api.progress.ProgressHandle;
76.71 +import org.netbeans.api.progress.ProgressHandleFactory;
76.72 +import org.netbeans.api.project.SourceGroup;
76.73 +import org.netbeans.api.queries.VisibilityQuery;
76.74 +import org.openide.filesystems.FileObject;
76.75 +import org.openide.filesystems.FileUtil;
76.76 +import org.openide.nodes.AbstractNode;
76.77 +import org.openide.nodes.FilterNode;
76.78 +import org.openide.nodes.Node;
76.79 +import org.openide.util.NbBundle;
76.80 +import org.openide.util.Parameters;
76.81 +import org.openide.util.WeakListeners;
76.82 +
76.83 +/**
76.84 + * Factory for package views.
76.85 + * @see org.netbeans.spi.project.ui.LogicalViewProvider
76.86 + * <p>
76.87 + * <b>This is copied from the corresponding Java action in java.projects</b>
76.88 + * </p>
76.89 + *
76.90 + * @author Jesse Glick
76.91 + */
76.92 +@NbBundle.Messages({"# {0} - Filename", "PackageView.find_packages_progress=Finding packages in {0}"})
76.93 +public class PackageView {
76.94 +
76.95 + private PackageView() {}
76.96 +
76.97 + /**
76.98 + * Create a node which will contain package-oriented view of a source group.
76.99 + * <p>
76.100 + * The precise structure of this node is <em>not</em> specified by the API
76.101 + * and is subject to arbitrary change (perhaps at user option).
76.102 + * Callers should not make assumptions about the nature of subnodes, the
76.103 + * code or display names of certain nodes, and so on. You may use cookies/lookup
76.104 + * to find if particular subnodes correspond to folders or files.
76.105 + * </p>
76.106 + * @param group a source group which should be represented
76.107 + * @return node which will display packages in given group
76.108 + */
76.109 + public static Node createPackageView( SourceGroup group ) {
76.110 + return new RootNode (group);
76.111 + }
76.112 +
76.113 + /**
76.114 + * Finds the node representing given object, if any.
76.115 + * The current implementation works only for {@link org.openide.filesystems.FileObject}s
76.116 + * and {@link org.openide.loaders.DataObject}s.
76.117 + * @param rootNode a node some descendant of which should contain the object
76.118 + * @param object object to find
76.119 + * @return a node representing the given object, or null if no such node was found
76.120 + */
76.121 + public static Node findPath(Node rootNode, Object object) {
76.122 +
76.123 + PackageRootNode.PathFinder pf = rootNode.getLookup().lookup(PackageRootNode.PathFinder.class);
76.124 +
76.125 + if ( pf != null ) {
76.126 + return pf.findPath( rootNode, object );
76.127 + } else {
76.128 + TreeRootNode.PathFinder pf2 = rootNode.getLookup().lookup(TreeRootNode.PathFinder.class);
76.129 + if (pf2 != null) {
76.130 + return pf2.findPath(rootNode, object);
76.131 + } else {
76.132 + return null;
76.133 + }
76.134 + }
76.135 + }
76.136 +
76.137 + /**
76.138 + * Create a list or combo box model suitable for {@link javax.swing.JList} from a source group
76.139 + * showing all Java packages in the source group.
76.140 + * To display it you will also need {@link #listRenderer}.
76.141 + * <p>No particular guarantees are made as to the nature of the model objects themselves,
76.142 + * except that {@link Object#toString} will give the fully-qualified package name
76.143 + * (or <code>""</code> for the default package), regardless of what the renderer
76.144 + * actually displays.</p>
76.145 + * @param group a Java-like source group
76.146 + * @return a model of its packages
76.147 + * @since org.netbeans.modules.java.project/1 1.3
76.148 + */
76.149 +
76.150 + public static ComboBoxModel createListView(SourceGroup group) {
76.151 + Parameters.notNull("group", group); //NOI18N
76.152 + SortedSet<PackageItem> data = new TreeSet<>();
76.153 + findNonExcludedPackages(null, data, group.getRootFolder(), group, false);
76.154 + return new DefaultComboBoxModel(data.toArray(new PackageItem[data.size()]));
76.155 + }
76.156 +
76.157 + /** Fills given collection with flattened packages under given folder
76.158 + *@param target The collection to be filled
76.159 + *@param fo The folder to be scanned
76.160 + * @param group the group to scan
76.161 + * @param createPackageItems if false the collection will be filled with file objects; if
76.162 + * true PackageItems will be created.
76.163 + * @param showProgress whether to show a progress handle or not
76.164 + */
76.165 + static void findNonExcludedPackages(PackageViewChildren children, Collection<PackageItem> target, FileObject fo, SourceGroup group, boolean showProgress) {
76.166 + if (showProgress) {
76.167 + ProgressHandle progress = ProgressHandleFactory.createHandle(NbBundle.getMessage(PackageView.class, "PackageView.find_packages_progress", FileUtil.getFileDisplayName(fo)));
76.168 + progress.start(1000);
76.169 + findNonExcludedPackages(children, target, fo, group, progress, 0, 1000);
76.170 + progress.finish();
76.171 + } else {
76.172 + findNonExcludedPackages(children, target, fo, group, null, 0, 0);
76.173 + }
76.174 + }
76.175 +
76.176 + private static void findNonExcludedPackages(PackageViewChildren children, Collection<PackageItem> target, FileObject fo, SourceGroup group, ProgressHandle progress, int start, int end) {
76.177 +
76.178 + assert fo.isFolder() : "Package view only accepts folders"; // NOI18N
76.179 +
76.180 + if (progress != null) {
76.181 + String path = FileUtil.getRelativePath(children.getRoot(), fo);
76.182 + assert path != null : fo + " in " + children.getRoot();
76.183 + progress.progress(path.replace('/', '.'), start);
76.184 + }
76.185 +
76.186 + if (!fo.isValid()) {
76.187 + return;
76.188 + }
76.189 +
76.190 + if ( !VisibilityQuery.getDefault().isVisible( fo ) ) {
76.191 + return; // Don't show hidden packages
76.192 + }
76.193 +
76.194 + boolean hasSubfolders = false;
76.195 + boolean hasFiles = false;
76.196 + List<FileObject> folders = new ArrayList<>();
76.197 + for (FileObject kid : fo.getChildren()) {
76.198 + if (kid.isValid() && VisibilityQuery.getDefault().isVisible(kid) && group.contains(kid)) {
76.199 + if (kid.isFolder()) {
76.200 + FileObject init = kid.getFileObject("__init__", "py"); //NOI18N
76.201 + if(init != null) {
76.202 + folders.add(kid);
76.203 + hasSubfolders = true;
76.204 + }
76.205 + }
76.206 + else {
76.207 + hasFiles = true;
76.208 + }
76.209 + }
76.210 + }
76.211 + if (hasFiles || !hasSubfolders) {
76.212 + if (target != null) {
76.213 + target.add( new PackageItem(group, fo, !hasFiles ) );
76.214 + }
76.215 + else {
76.216 + if (fo.isValid()) {
76.217 + children.add(fo, !hasFiles, false);
76.218 + }
76.219 + }
76.220 + }
76.221 + if (!folders.isEmpty()) {
76.222 + int diff = (end - start) / folders.size();
76.223 + int c = 0;
76.224 + for (FileObject kid : folders) {
76.225 + // Do this after adding the parent, so we get a pre-order traversal.
76.226 + // Also see PackageViewChildren.findChild: prefer to get root first.
76.227 + findNonExcludedPackages(children, target, kid, group, progress, start + c * diff, start + (c + 1) * diff);
76.228 + c++;
76.229 + }
76.230 + }
76.231 + }
76.232 +
76.233 +// public static ComboBoxModel createListView(SourceGroup group) {
76.234 +// DefaultListModel model = new DefaultListModel();
76.235 +// SortedSet/*<PackageItem>*/ items = new TreeSet();
76.236 +// FileObject root = group.getRootFolder();
76.237 +// if (PackageDisplayUtils.isSignificant(root)) {
76.238 +// items.add(new PackageItem(group, root));
76.239 +// }
76.240 +// Enumeration/*<FileObject>*/ files = root.getChildren(true);
76.241 +// while (files.hasMoreElements()) {
76.242 +// FileObject f = (FileObject) files.nextElement();
76.243 +// if (f.isFolder() && PackageDisplayUtils.isSignificant(f)) {
76.244 +// items.add(new PackageItem(group, f));
76.245 +// }
76.246 +// }
76.247 +// return new DefaultComboBoxModel(items.toArray(new PackageItem[items.size()]));
76.248 +// }
76.249 +
76.250 +
76.251 + /**
76.252 + * Create a renderer suited to rendering models created using {@link #createListView}.
76.253 + * The exact nature of the display is not specified.
76.254 + * Instances of String can also be rendered.
76.255 + * @return a suitable package renderer
76.256 + * @since org.netbeans.modules.java.project/1 1.3
76.257 + */
76.258 + public static ListCellRenderer listRenderer() {
76.259 + return new PackageListCellRenderer();
76.260 + }
76.261 +
76.262 + /**
76.263 + * FilterNode which listens on the PackageViewSettings and changes the view to
76.264 + * the package view or tree view
76.265 + *
76.266 + */
76.267 + private static final class RootNode extends FilterNode implements PropertyChangeListener {
76.268 +
76.269 + private final SourceGroup sourceGroup;
76.270 +
76.271 + @SuppressWarnings("LeakingThisInConstructor")
76.272 + private RootNode (SourceGroup group) {
76.273 + super(getOriginalNode(group));
76.274 + this.sourceGroup = group;
76.275 + PythonProjectSettings.addPropertyChangeListener(WeakListeners.propertyChange(this, PythonProjectSettings.class));
76.276 + group.addPropertyChangeListener(WeakListeners.propertyChange(this, group));
76.277 + }
76.278 +
76.279 + @Override
76.280 + public void propertyChange (PropertyChangeEvent event) {
76.281 + String prop = event.getPropertyName();
76.282 + if (PythonProjectSettings.PROP_PACKAGE_VIEW_TYPE.equals(prop) || SourceGroup.PROP_CONTAINERSHIP.equals(prop)) {
76.283 + EventQueue.invokeLater(new Runnable() {
76.284 + @Override
76.285 + public void run() {
76.286 + changeOriginal(getOriginalNode(sourceGroup), true);
76.287 + }
76.288 + });
76.289 + }
76.290 + }
76.291 +
76.292 + private static Node getOriginalNode(SourceGroup group) {
76.293 + FileObject root = group.getRootFolder();
76.294 + //Guard condition, if the project is (closed) and deleted but not yet gced
76.295 + // and the view is switched, the source group is not valid.
76.296 + if ( root == null || !root.isValid()) {
76.297 + return new AbstractNode (Children.LEAF);
76.298 + }
76.299 + switch (PythonProjectSettings.getPackageViewType()) {
76.300 + case PythonProjectSettings.TYPE_PACKAGE_VIEW:
76.301 + return new PackageRootNode(group);
76.302 + case PythonProjectSettings.TYPE_TREE:
76.303 + return new TreeRootNode(group);
76.304 + default:
76.305 + assert false : "Unknown PackageView Type"; //NOI18N
76.306 + return new PackageRootNode(group);
76.307 + }
76.308 + }
76.309 + }
76.310 +
76.311 + /**
76.312 + * Model item representing one package.
76.313 + */
76.314 + static final class PackageItem implements Comparable<PackageItem> {
76.315 +
76.316 + private static final Map<Image,Icon> image2icon = new IdentityHashMap<>();
76.317 +
76.318 + private final boolean empty;
76.319 + private final FileObject pkg;
76.320 + private final String pkgname;
76.321 + private Icon icon;
76.322 +
76.323 + public PackageItem(SourceGroup group, FileObject pkg, boolean empty) {
76.324 + this.pkg = pkg;
76.325 + this.empty = empty;
76.326 + String path = FileUtil.getRelativePath(group.getRootFolder(), pkg);
76.327 + assert path != null : "No " + pkg + " in " + group;
76.328 + pkgname = path.replace('/', '.');
76.329 + }
76.330 +
76.331 + @Override
76.332 + public String toString() {
76.333 + return pkgname;
76.334 + }
76.335 +
76.336 + public String getLabel() {
76.337 + return PackageDisplayUtils.getDisplayLabel(pkgname);
76.338 + }
76.339 +
76.340 + public Icon getIcon() {
76.341 + if ( icon == null ) {
76.342 + Image image = PackageDisplayUtils.getIcon(pkg, pkgname, empty);
76.343 + icon = image2icon.get(image);
76.344 + if ( icon == null ) {
76.345 + icon = new ImageIcon( image );
76.346 + image2icon.put( image, icon );
76.347 + }
76.348 + }
76.349 + return icon;
76.350 + }
76.351 +
76.352 + @Override
76.353 + public int compareTo(PackageItem p) {
76.354 + return pkgname.compareTo(p.pkgname);
76.355 + }
76.356 +
76.357 + }
76.358 +
76.359 + /**
76.360 + * The renderer which just displays {@link PackageItem#getLabel} and {@link PackageItem#getIcon}.
76.361 + */
76.362 + private static final class PackageListCellRenderer extends JLabel implements ListCellRenderer, UIResource {
76.363 +
76.364 + public PackageListCellRenderer() {
76.365 + setOpaque(true);
76.366 + }
76.367 +
76.368 + @Override
76.369 + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
76.370 + // #93658: GTK needs name to render cell renderer "natively"
76.371 + setName("ComboBox.listRenderer"); // NOI18N
76.372 +
76.373 + if (value instanceof PackageItem) {
76.374 + PackageItem pkgitem = (PackageItem) value;
76.375 + setText(pkgitem.getLabel());
76.376 + setIcon(pkgitem.getIcon());
76.377 + } else {
76.378 + // #49954: render a specially inserted package somehow.
76.379 + String pkgitem = (String) value;
76.380 + setText(pkgitem);
76.381 + setIcon(null);
76.382 + }
76.383 +
76.384 + if ( isSelected ) {
76.385 + setBackground(list.getSelectionBackground());
76.386 + setForeground(list.getSelectionForeground());
76.387 + }
76.388 + else {
76.389 + setBackground(list.getBackground());
76.390 + setForeground(list.getForeground());
76.391 + }
76.392 +
76.393 + return this;
76.394 + }
76.395 +
76.396 + // #93658: GTK needs name to render cell renderer "natively"
76.397 + @Override
76.398 + public String getName() {
76.399 + String name = super.getName();
76.400 + return name == null ? "ComboBox.renderer" : name; // NOI18N
76.401 + }
76.402 +
76.403 + }
76.404 +
76.405 +
76.406 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/PackageViewChildren.java Tue Feb 24 01:58:36 2015 -0800
77.3 @@ -0,0 +1,1332 @@
77.4 +/*
77.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77.6 + *
77.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
77.8 + *
77.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
77.10 + * Other names may be trademarks of their respective owners.
77.11 + *
77.12 + * The contents of this file are subject to the terms of either the GNU
77.13 + * General Public License Version 2 only ("GPL") or the Common
77.14 + * Development and Distribution License("CDDL") (collectively, the
77.15 + * "License"). You may not use this file except in compliance with the
77.16 + * License. You can obtain a copy of the License at
77.17 + * http://www.netbeans.org/cddl-gplv2.html
77.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
77.19 + * specific language governing permissions and limitations under the
77.20 + * License. When distributing the software, include this License Header
77.21 + * Notice in each file and include the License file at
77.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
77.23 + * particular file as subject to the "Classpath" exception as provided
77.24 + * by Oracle in the GPL Version 2 section of the License file that
77.25 + * accompanied this code. If applicable, add the following below the
77.26 + * License Header, with the fields enclosed by brackets [] replaced by
77.27 + * your own identifying information:
77.28 + * "Portions Copyrighted [year] [name of copyright owner]"
77.29 + *
77.30 + * Contributor(s):
77.31 + *
77.32 + * The Original Software is NetBeans. The Initial Developer of the Original
77.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
77.34 + * Microsystems, Inc. All Rights Reserved.
77.35 + *
77.36 + * If you wish your version of this file to be governed by only the CDDL
77.37 + * or only the GPL Version 2, indicate your decision by adding
77.38 + * "[Contributor] elects to include this software in this distribution
77.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
77.40 + * single choice of license, a recipient has the option to distribute
77.41 + * your version of this file under either the CDDL, the GPL Version 2 or
77.42 + * to extend the choice of license to its licensees as provided above.
77.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
77.44 + * Version 2 license, then the option applies only if the new code is
77.45 + * made subject to such option by the copyright holder.
77.46 + */
77.47 +
77.48 +package org.netbeans.modules.python.project2.ui;
77.49 +
77.50 +import java.awt.EventQueue;
77.51 +import java.awt.Image;
77.52 +import java.awt.datatransfer.DataFlavor;
77.53 +import java.awt.datatransfer.Transferable;
77.54 +import java.awt.datatransfer.UnsupportedFlavorException;
77.55 +import java.awt.dnd.DnDConstants;
77.56 +import java.beans.PropertyChangeEvent;
77.57 +import java.beans.PropertyChangeListener;
77.58 +import java.beans.PropertyChangeSupport;
77.59 +import java.io.IOException;
77.60 +import java.lang.reflect.InvocationTargetException;
77.61 +import java.text.MessageFormat;
77.62 +import java.util.ArrayList;
77.63 +import java.util.Collections;
77.64 +import java.util.HashSet;
77.65 +import java.util.Iterator;
77.66 +import java.util.List;
77.67 +import java.util.Set;
77.68 +import java.util.StringTokenizer;
77.69 +import java.util.TreeMap;
77.70 +import java.util.TreeSet;
77.71 +import javax.swing.Action;
77.72 +import javax.swing.SwingUtilities;
77.73 +import javax.swing.event.ChangeEvent;
77.74 +import javax.swing.event.ChangeListener;
77.75 +import org.netbeans.api.fileinfo.NonRecursiveFolder;
77.76 +import org.netbeans.api.project.SourceGroup;
77.77 +import org.netbeans.api.queries.VisibilityQuery;
77.78 +import org.netbeans.spi.project.ActionProvider;
77.79 +import org.netbeans.spi.project.ui.support.FileSensitiveActions;
77.80 +import org.openide.DialogDisplayer;
77.81 +import org.openide.ErrorManager;
77.82 +import org.openide.NotifyDescriptor;
77.83 +import org.openide.actions.FileSystemAction;
77.84 +import org.openide.actions.PropertiesAction;
77.85 +import org.openide.filesystems.FileAttributeEvent;
77.86 +import org.openide.filesystems.FileChangeListener;
77.87 +import org.openide.filesystems.FileEvent;
77.88 +import org.openide.filesystems.FileObject;
77.89 +import org.openide.filesystems.FileRenameEvent;
77.90 +import org.openide.filesystems.FileStateInvalidException;
77.91 +import org.openide.filesystems.FileSystem;
77.92 +import org.openide.filesystems.FileUtil;
77.93 +import org.openide.loaders.ChangeableDataFilter;
77.94 +import org.openide.loaders.DataFilter;
77.95 +import org.openide.loaders.DataFolder;
77.96 +import org.openide.loaders.DataObject;
77.97 +import org.openide.nodes.Children;
77.98 +import org.openide.nodes.FilterNode;
77.99 +import org.openide.nodes.Node;
77.100 +import org.openide.nodes.PropertySupport;
77.101 +import org.openide.nodes.Sheet;
77.102 +import org.openide.util.ChangeSupport;
77.103 +import org.openide.util.Exceptions;
77.104 +import org.openide.util.ImageUtilities;
77.105 +import org.openide.util.NbBundle;
77.106 +import org.openide.util.RequestProcessor;
77.107 +import org.openide.util.WeakListeners;
77.108 +import org.openide.util.datatransfer.ExTransferable;
77.109 +import org.openide.util.datatransfer.MultiTransferObject;
77.110 +import org.openide.util.datatransfer.PasteType;
77.111 +import org.openide.util.lookup.Lookups;
77.112 +import org.openide.util.lookup.ProxyLookup;
77.113 +
77.114 +/**
77.115 + * Display of Java sources in a package structure rather than folder structure.
77.116 + *
77.117 + * <p>
77.118 + * <b>This is copied from the corresponding Java action in java.projects</b>
77.119 + * </p>
77.120 + *
77.121 + * @author Adam Sotona, Jesse Glick, Petr Hrebejk, Tomas Zezula
77.122 + */
77.123 +@NbBundle.Messages({"TXT_PastePackage=Paste Package",
77.124 + "MSG_InvalidPackageName=Name is not a valid Java package.",
77.125 + "LBL_CompilePackage_Action=Compile Package",
77.126 + "PROP_name=Name",
77.127 + "HINT_name=Package Name"})
77.128 +final class PackageViewChildren extends Children.Keys<String> implements FileChangeListener, ChangeListener, Runnable {
77.129 +
77.130 + private static final String NODE_NOT_CREATED = "NNC"; // NOI18N
77.131 + private static final String NODE_NOT_CREATED_EMPTY = "NNC_E"; //NOI18N
77.132 +
77.133 + private static final MessageFormat PACKAGE_FLAVOR = new MessageFormat("application/x-python-org-netbeans-modules-python-project-packagenodednd; class=org.netbeans.spi.java.project.support.ui.PackageViewChildren$PackageNode; mask={0}"); //NOI18N
77.134 +
77.135 + static final String PRIMARY_TYPE = "application"; //NOI18N
77.136 + static final String SUBTYPE = "x-python-org-netbeans-modules-python-project-packagenodednd"; //NOI18N
77.137 + static final String MASK = "mask"; //NOI18N
77.138 +
77.139 + private java.util.Map<String,Object/*NODE_NOT_CREATED|NODE_NOT_CREATED_EMPTY|PackageNode*/> names2nodes;
77.140 + private final FileObject root;
77.141 + private final SourceGroup group;
77.142 + private FileChangeListener wfcl; // Weak listener on the system filesystem
77.143 + private ChangeListener wvqcl; // Weak listener on the VisibilityQuery
77.144 +
77.145 + /**
77.146 + * Creates children based on a single source root.
77.147 + * @param root the folder where sources start (must be a package root)
77.148 + */
77.149 + public PackageViewChildren(SourceGroup group) {
77.150 +
77.151 + // Sem mas dat cache a bude to uplne nejrychlejsi na svete
77.152 +
77.153 + this.root = group.getRootFolder();
77.154 + this.group = group;
77.155 + }
77.156 +
77.157 + FileObject getRoot() {
77.158 + return root; // Used from PackageRootNode
77.159 + }
77.160 +
77.161 + @Override
77.162 + protected Node[] createNodes(String path) {
77.163 + FileObject fo = root.getFileObject(path);
77.164 + if ( fo != null && fo.isValid()) {
77.165 + Object o = names2nodes.get(path);
77.166 + PackageNode n;
77.167 + DataFolder folder = DataFolder.findFolder(fo);
77.168 + if (folder.isValid()) {
77.169 + if ( o == NODE_NOT_CREATED ) {
77.170 + n = new PackageNode(root, folder, false);
77.171 + } else { // NODE_NOT_CREATED_EMPTY, PackageNode
77.172 + n = new PackageNode(root, folder);
77.173 + }
77.174 + names2nodes.put(path, n);
77.175 + return new Node[] {n};
77.176 + }
77.177 + }
77.178 + return new Node[0];
77.179 + }
77.180 +
77.181 + RequestProcessor.Task task = RequestProcessor.getDefault().create( this );
77.182 +
77.183 + @Override
77.184 + protected void addNotify() {
77.185 + // System.out.println("ADD NOTIFY" + root + " : " + this );
77.186 + super.addNotify();
77.187 + task.schedule( 0 );
77.188 + }
77.189 +
77.190 + @Override
77.191 + public Node[] getNodes( boolean optimal ) {
77.192 + if ( optimal ) {
77.193 + Node[] garbage = super.getNodes( false );
77.194 + task.waitFinished();
77.195 + }
77.196 + return super.getNodes( false );
77.197 + }
77.198 +
77.199 + @Override
77.200 + public Node findChild (String name) {
77.201 + while (true) {
77.202 + Node n = super.findChild(name);
77.203 + if (n != null) {
77.204 + // If already there, get it quickly.
77.205 + return n;
77.206 + }
77.207 + // In case a project is made on a large existing source root,
77.208 + // which happens to have a file in the root dir (so package node
77.209 + // should exist), try to select the root package node soon; no need
77.210 + // to wait for whole tree.
77.211 + try {
77.212 + if (task.waitFinished(5000)) {
77.213 + return super.findChild(name);
77.214 + }
77.215 + // refreshKeysAsync won't run since we are blocking EQ!
77.216 + refreshKeys();
77.217 + } catch (InterruptedException x) {
77.218 + Exceptions.printStackTrace(x);
77.219 + }
77.220 + }
77.221 + }
77.222 +
77.223 + @Override
77.224 + public void run() {
77.225 + computeKeys();
77.226 + refreshKeys();
77.227 + try {
77.228 + FileSystem fs = root.getFileSystem();
77.229 + wfcl = FileUtil.weakFileChangeListener(this, fs);
77.230 + fs.addFileChangeListener( wfcl );
77.231 + }
77.232 + catch ( FileStateInvalidException e ) {
77.233 + ErrorManager.getDefault().notify( ErrorManager.INFORMATIONAL, e );
77.234 + }
77.235 + wvqcl = WeakListeners.change( this, VisibilityQuery.getDefault() );
77.236 + VisibilityQuery.getDefault().addChangeListener( wvqcl );
77.237 + }
77.238 +
77.239 + @Override
77.240 + protected void removeNotify() {
77.241 + // System.out.println("REMOVE NOTIFY" + root + " : " + this );
77.242 + VisibilityQuery.getDefault().removeChangeListener( wvqcl );
77.243 + try {
77.244 + root.getFileSystem().removeFileChangeListener( wfcl );
77.245 + }
77.246 + catch ( FileStateInvalidException e ) {
77.247 + ErrorManager.getDefault().notify( ErrorManager.INFORMATIONAL, e );
77.248 + }
77.249 + setKeys(new String[0]);
77.250 + names2nodes.clear();
77.251 + super.removeNotify();
77.252 + }
77.253 +
77.254 + // Private methods ---------------------------------------------------------
77.255 +
77.256 + private void refreshKeys() {
77.257 + Set<String> keys;
77.258 + synchronized (names2nodes) {
77.259 + keys = new TreeSet<>(names2nodes.keySet());
77.260 + }
77.261 + setKeys(keys);
77.262 + }
77.263 +
77.264 + /* #70097: workaround of a javacore deadlock
77.265 + * See related issue: #61027
77.266 + */
77.267 + private void refreshKeysAsync () {
77.268 + EventQueue.invokeLater(new Runnable() {
77.269 + @Override
77.270 + public void run () {
77.271 + refreshKeys();
77.272 + }
77.273 + });
77.274 + }
77.275 +
77.276 + private void computeKeys() {
77.277 + // XXX this is not going to perform too well for a huge source root...
77.278 + // However we have to go through the whole hierarchy in order to find
77.279 + // all packages (Hrebejk)
77.280 + names2nodes = Collections.synchronizedMap(new TreeMap<String,Object>());
77.281 + findNonExcludedPackages( root );
77.282 + }
77.283 +
77.284 + /**
77.285 + * Collect all recursive subfolders, except those which have subfolders
77.286 + * but no files.
77.287 + */
77.288 + private void findNonExcludedPackages( FileObject fo ) {
77.289 + PackageView.findNonExcludedPackages(this, null, fo, group, true);
77.290 + }
77.291 +
77.292 +
77.293 + /** Finds all empty parents of given package and deletes them
77.294 + */
77.295 + private void cleanEmptyKeys( FileObject fo ) {
77.296 + FileObject parent = fo.getParent();
77.297 +
77.298 + // Special case for default package
77.299 + if ( root.equals( parent ) ) {
77.300 + PackageNode n = get( parent );
77.301 + // the default package is considered empty if it only contains folders,
77.302 + // regardless of the contents of these folders (empty or not)
77.303 + if ( n != null && PackageDisplayUtils.isEmpty( root, false, false ) ) {
77.304 + remove( root );
77.305 + }
77.306 + return;
77.307 + }
77.308 +
77.309 + while ( FileUtil.isParentOf( root, parent ) ) {
77.310 + PackageNode n = get( parent );
77.311 + if ( n != null && n.isLeaf() ) {
77.312 + // System.out.println("Cleaning " + parent);
77.313 + remove( parent );
77.314 + }
77.315 + parent = parent.getParent();
77.316 + }
77.317 + }
77.318 +
77.319 + // Non private only to be able to have the findNonExcludedPackages impl
77.320 + // in on place (PackageView)
77.321 + void add(FileObject fo, boolean empty, boolean refreshImmediately) {
77.322 + String path = FileUtil.getRelativePath( root, fo );
77.323 + assert path != null : "Adding wrong folder " + fo +"(valid="+fo.isValid()+")"+ "under root" + this.root + "(valid="+this.root.isValid()+")";
77.324 + if ( get( fo ) == null ) {
77.325 + names2nodes.put( path, empty ? NODE_NOT_CREATED_EMPTY : NODE_NOT_CREATED );
77.326 + if (refreshImmediately) {
77.327 + refreshKeysAsync();
77.328 + } else {
77.329 + synchronized (this) {
77.330 + if (refreshLazilyTask == null) {
77.331 + refreshLazilyTask = RequestProcessor.getDefault().post(new Runnable() {
77.332 + @Override
77.333 + public void run() {
77.334 + synchronized (PackageViewChildren.this) {
77.335 + refreshLazilyTask = null;
77.336 + refreshKeysAsync();
77.337 + }
77.338 + }
77.339 + }, 2500);
77.340 + }
77.341 + }
77.342 + }
77.343 + }
77.344 + }
77.345 + private RequestProcessor.Task refreshLazilyTask;
77.346 +
77.347 + private void remove( FileObject fo ) {
77.348 + String path = FileUtil.getRelativePath( root, fo );
77.349 + assert path != null : "Removing wrong folder" + fo;
77.350 + names2nodes.remove( path );
77.351 + }
77.352 +
77.353 + private void removeSubTree (FileObject fo) {
77.354 + String path = FileUtil.getRelativePath( root, fo );
77.355 + assert path != null : "Removing wrong folder" + fo;
77.356 + synchronized (names2nodes) {
77.357 + Set<String> keys = names2nodes.keySet();
77.358 + keys.remove(path);
77.359 + path = path + '/'; //NOI18N
77.360 + Iterator<String> it = keys.iterator();
77.361 + while (it.hasNext()) {
77.362 + if (it.next().startsWith(path)) {
77.363 + it.remove();
77.364 + }
77.365 + }
77.366 + }
77.367 + }
77.368 +
77.369 + private PackageNode get( FileObject fo ) {
77.370 + String path = FileUtil.getRelativePath( root, fo );
77.371 + assert path != null : "Asking for wrong folder" + fo;
77.372 + Object o = names2nodes.get( path );
77.373 + return !isNodeCreated( o ) ? null : (PackageNode)o;
77.374 + }
77.375 +
77.376 + private boolean contains( FileObject fo ) {
77.377 + String path = FileUtil.getRelativePath( root, fo );
77.378 + assert path != null : "Asking for wrong folder" + fo;
77.379 + Object o = names2nodes.get( path );
77.380 + return o != null;
77.381 + }
77.382 +
77.383 + private boolean exists( FileObject fo ) {
77.384 + String path = FileUtil.getRelativePath( root, fo );
77.385 + return names2nodes.get( path ) != null;
77.386 + }
77.387 +
77.388 + private boolean isNodeCreated( Object o ) {
77.389 + return o instanceof Node;
77.390 + }
77.391 +
77.392 + private PackageNode updatePath( String oldPath, String newPath ) {
77.393 + assert newPath != null;
77.394 + Object o = names2nodes.get( oldPath );
77.395 + if ( o == null ) {
77.396 + return null;
77.397 + }
77.398 + names2nodes.remove( oldPath );
77.399 + names2nodes.put( newPath, o );
77.400 + return !isNodeCreated( o ) ? null : (PackageNode)o;
77.401 + }
77.402 +
77.403 + // Implementation of FileChangeListener ------------------------------------
77.404 +
77.405 + @Override
77.406 + public void fileAttributeChanged( FileAttributeEvent fe ) {}
77.407 +
77.408 + @Override
77.409 + public void fileChanged( FileEvent fe ) {}
77.410 +
77.411 + @Override
77.412 + public void fileFolderCreated( FileEvent fe ) {
77.413 + FileObject fo = fe.getFile();
77.414 + if ( FileUtil.isParentOf( root, fo ) && isVisible( root, fo ) ) {
77.415 + cleanEmptyKeys( fo );
77.416 +// add( fo, false);
77.417 + findNonExcludedPackages( fo );
77.418 + refreshKeys();
77.419 + }
77.420 + }
77.421 +
77.422 + @Override
77.423 + public void fileDataCreated( FileEvent fe ) {
77.424 + FileObject fo = fe.getFile();
77.425 + if ( FileUtil.isParentOf( root, fo ) && isVisible( root, fo ) ) {
77.426 + FileObject parent = fo.getParent();
77.427 + // XXX consider using group.contains() here
77.428 + if ( !VisibilityQuery.getDefault().isVisible( parent ) ) {
77.429 + return; // Adding file into ignored directory
77.430 + }
77.431 + PackageNode n = get( parent );
77.432 + if ( n == null && !contains( parent ) ) {
77.433 + add(parent, false, true);
77.434 + refreshKeys();
77.435 + }
77.436 + else if ( n != null ) {
77.437 + n.updateChildren();
77.438 + }
77.439 + }
77.440 + }
77.441 +
77.442 + @Override
77.443 + public void fileDeleted( FileEvent fe ) {
77.444 + FileObject fo = fe.getFile();
77.445 +
77.446 + // System.out.println("FILE DELETED " + FileUtil.getRelativePath( root, fo ) );
77.447 +
77.448 + if ( FileUtil.isParentOf( root, fo ) && isVisible( root, fo ) ) {
77.449 +
77.450 + // System.out.println("IS FOLDER? " + fo + " : " + fo.isFolder() );
77.451 + /* Hack for MasterFS see #42464 */
77.452 + if ( fo.isFolder() || get( fo ) != null ) {
77.453 + // System.out.println("REMOVING FODER " + fo );
77.454 + removeSubTree( fo );
77.455 + // Now add the parent if necessary
77.456 + FileObject parent = fo.getParent();
77.457 + if ( ( FileUtil.isParentOf( root, parent ) || root.equals( parent ) ) && get( parent ) == null && parent.isValid() ) {
77.458 + // Candidate for adding
77.459 + if ( !toBeRemoved( parent ) ) {
77.460 + // System.out.println("ADDING PARENT " + parent );
77.461 + add(parent, true, true);
77.462 + }
77.463 + }
77.464 + refreshKeysAsync();
77.465 + }
77.466 + else {
77.467 + FileObject parent = fo.getParent();
77.468 + final PackageNode n = get( parent );
77.469 + if ( n != null ) {
77.470 + //#61027: workaround to a deadlock when the package is being changed from non-leaf to leaf:
77.471 + boolean leaf = n.isLeaf();
77.472 + DataFolder df = n.getDataFolder();
77.473 + boolean empty = isEmpty(df);
77.474 +
77.475 + if (leaf != empty) {
77.476 + SwingUtilities.invokeLater(new Runnable() {
77.477 + @Override
77.478 + public void run() {
77.479 + n.updateChildren();
77.480 + }
77.481 + });
77.482 + } else {
77.483 + n.updateChildren();
77.484 + }
77.485 + }
77.486 + // If the parent folder only contains folders remove it
77.487 + if ( toBeRemoved( parent ) ) {
77.488 + remove( parent );
77.489 + refreshKeysAsync();
77.490 + }
77.491 +
77.492 + }
77.493 + }
77.494 + // else {
77.495 + // System.out.println("NOT A PARENT " + fo );
77.496 + // }
77.497 + }
77.498 +
77.499 + /** Returns true if the folder should be removed from the view
77.500 + * i.e. it has some unignored children and the children are folders only
77.501 + */
77.502 + private boolean toBeRemoved( FileObject folder ) {
77.503 + boolean ignoredOnly = true;
77.504 + boolean foldersOnly = true;
77.505 + for (FileObject kid : folder.getChildren()) {
77.506 + // XXX consider using group.contains() here
77.507 + if (VisibilityQuery.getDefault().isVisible(kid)) {
77.508 + ignoredOnly = false;
77.509 + if (!kid.isFolder()) {
77.510 + foldersOnly = false;
77.511 + break;
77.512 + }
77.513 + }
77.514 + }
77.515 + if ( ignoredOnly ) {
77.516 + return false; // It is either empty or it only contains ignored files
77.517 + // thus is leaf and it means package
77.518 + }
77.519 + else {
77.520 + return foldersOnly;
77.521 + }
77.522 + }
77.523 +
77.524 +
77.525 + @Override
77.526 + public void fileRenamed( FileRenameEvent fe ) {
77.527 + FileObject fo = fe.getFile();
77.528 + if ( FileUtil.isParentOf( root, fo ) && fo.isFolder() ) {
77.529 + String rp = FileUtil.getRelativePath( root, fo.getParent() );
77.530 + String oldPath = rp + ( rp.length() == 0 ? "" : "/" ) + fe.getName() + fe.getExt(); // NOI18N
77.531 +
77.532 + // XXX consider using group.contains() here
77.533 + boolean visible = VisibilityQuery.getDefault().isVisible( fo );
77.534 + boolean doUpdate = false;
77.535 +
77.536 + // Find all entries which have to be updated
77.537 + List<String> needsUpdate = new ArrayList<>();
77.538 + synchronized (names2nodes) {
77.539 + for (Iterator<String> it = names2nodes.keySet().iterator(); it.hasNext(); ) {
77.540 + String p = it.next();
77.541 + if ( p.startsWith( oldPath ) ) {
77.542 + if ( visible ) {
77.543 + needsUpdate.add( p );
77.544 + } else {
77.545 + it.remove();
77.546 + doUpdate = true;
77.547 + }
77.548 + }
77.549 + }
77.550 + }
77.551 +
77.552 + // If the node does not exists then there might have been update
77.553 + // from ignored to non ignored
77.554 + if ( get( fo ) == null && visible ) {
77.555 + cleanEmptyKeys( fo );
77.556 + findNonExcludedPackages( fo );
77.557 + doUpdate = true; // force refresh
77.558 + }
77.559 +
77.560 + int oldPathLen = oldPath.length();
77.561 + String newPath = FileUtil.getRelativePath( root, fo );
77.562 + for (String p : needsUpdate) {
77.563 + StringBuilder np = new StringBuilder(p);
77.564 + np.replace( 0, oldPathLen, newPath );
77.565 + PackageNode n = updatePath( p, np.toString() ); // Replace entries in cache
77.566 + if ( n != null ) {
77.567 + n.updateDisplayName(); // Update nodes
77.568 + }
77.569 + }
77.570 +
77.571 + if ( needsUpdate.size() > 1 || doUpdate ) {
77.572 + // Sorting might change
77.573 + refreshKeys();
77.574 + }
77.575 + }
77.576 + /*
77.577 + else if ( FileUtil.isParentOf( root, fo ) && fo.isFolder() ) {
77.578 + FileObject parent = fo.getParent();
77.579 + PackageNode n = get( parent );
77.580 + if ( n != null && VisibilityQuery.getDefault().isVisible( parent ) ) {
77.581 + n.updateChildren();
77.582 + }
77.583 +
77.584 + }
77.585 + */
77.586 +
77.587 + }
77.588 +
77.589 + /** Test whether file and all it's parent up to parent paremeter
77.590 + * are visible
77.591 + */
77.592 + private boolean isVisible( FileObject parent, FileObject file ) {
77.593 +
77.594 + do {
77.595 + // XXX consider using group.contains() here
77.596 + if ( !VisibilityQuery.getDefault().isVisible( file ) ) {
77.597 + return false;
77.598 + }
77.599 + file = file.getParent();
77.600 + }
77.601 + while ( file != null && file != parent );
77.602 +
77.603 + return true;
77.604 + }
77.605 +
77.606 +
77.607 + // Implementation of ChangeListener ------------------------------------
77.608 +
77.609 + @Override
77.610 + public void stateChanged( ChangeEvent e ) {
77.611 + computeKeys();
77.612 + refreshKeys();
77.613 + }
77.614 +
77.615 +
77.616 + /*
77.617 + private void debugKeySet() {
77.618 + for( Iterator it = names2nodes.keySet().iterator(); it.hasNext(); ) {
77.619 + String k = (String)it.next();
77.620 + System.out.println( " " + k + " -> " + names2nodes.get( k ) );
77.621 + }
77.622 + }
77.623 + */
77.624 +
77.625 + private final DataFilter NO_FOLDERS_FILTER = new NoFoldersDataFilter();
77.626 +
77.627 + private static boolean isEmpty(DataFolder dataFolder) {
77.628 + if ( dataFolder == null ) {
77.629 + return true;
77.630 + }
77.631 + return PackageDisplayUtils.isEmpty( dataFolder.getPrimaryFile() );
77.632 + }
77.633 +
77.634 + final class PackageNode extends FilterNode {
77.635 +
77.636 + private Action actions[];
77.637 +
77.638 + private final FileObject root;
77.639 + private DataFolder dataFolder;
77.640 + private boolean isDefaultPackage;
77.641 +
77.642 + public PackageNode( FileObject root, DataFolder dataFolder ) {
77.643 + this( root, dataFolder, isEmpty( dataFolder ) );
77.644 + }
77.645 +
77.646 + public PackageNode( FileObject root, DataFolder dataFolder, boolean empty ) {
77.647 + super( dataFolder.getNodeDelegate(),
77.648 + empty ? Children.LEAF : dataFolder.createNodeChildren( NO_FOLDERS_FILTER ),
77.649 + new ProxyLookup(
77.650 + Lookups.singleton(new NoFoldersContainer (dataFolder)),
77.651 + dataFolder.getNodeDelegate().getLookup()
77.652 +// Lookups.singleton(PackageRootNode.alwaysSearchableSearchInfo(SearchInfoFactory.createSearchInfo(
77.653 +// dataFolder.getPrimaryFile(),
77.654 +// false, //not recursive
77.655 +// new FileObjectFilter[] {
77.656 +// SearchInfoFactory.VISIBILITY_FILTER})
77.657 + ));
77.658 + this.root = root;
77.659 + this.dataFolder = dataFolder;
77.660 + this.isDefaultPackage = root.equals( dataFolder.getPrimaryFile() );
77.661 + }
77.662 +
77.663 + FileObject getRoot() {
77.664 + return root; // Used from PackageRootNode
77.665 + }
77.666 +
77.667 +
77.668 + @Override
77.669 + public String getName() {
77.670 + String relativePath = FileUtil.getRelativePath(root, dataFolder.getPrimaryFile());
77.671 + return relativePath == null ? null : relativePath.replace('/', '.'); // NOI18N
77.672 + }
77.673 +
77.674 + @Override
77.675 + public Action[] getActions( boolean context ) {
77.676 +
77.677 + if ( !context ) {
77.678 + if ( actions == null ) {
77.679 + // Copy actions and leave out the PropertiesAction and FileSystemAction.
77.680 + Action superActions[] = super.getActions( context );
77.681 + List<Action> actionList = new ArrayList<>(superActions.length);
77.682 +
77.683 + for( int i = 0; i < superActions.length; i++ ) {
77.684 +
77.685 + if ( (i <= superActions.length - 2) && superActions[ i ] == null && superActions[i + 1] instanceof PropertiesAction ) {
77.686 + i ++;
77.687 + continue;
77.688 + }
77.689 + else if ( superActions[i] instanceof PropertiesAction ) {
77.690 + continue;
77.691 + }
77.692 + else if ( superActions[i] instanceof FileSystemAction ) {
77.693 + actionList.add (null); // insert separator and new action
77.694 + actionList.add (FileSensitiveActions.fileCommandAction(ActionProvider.COMMAND_COMPILE_SINGLE,
77.695 + NbBundle.getMessage( PackageViewChildren.class, "LBL_CompilePackage_Action" ), // NOI18N
77.696 + null ));
77.697 + }
77.698 +
77.699 + actionList.add( superActions[i] );
77.700 + }
77.701 +
77.702 + actions = new Action[ actionList.size() ];
77.703 + actionList.toArray( actions );
77.704 + }
77.705 + return actions;
77.706 + }
77.707 + else {
77.708 + return super.getActions( context );
77.709 + }
77.710 + }
77.711 +
77.712 + @Override
77.713 + public boolean canRename() {
77.714 + return !isDefaultPackage;
77.715 + }
77.716 +
77.717 + @Override
77.718 + public boolean canCut () {
77.719 + return !isDefaultPackage;
77.720 + }
77.721 +
77.722 + /**
77.723 + * Copy handling
77.724 + */
77.725 + @Override
77.726 + public Transferable clipboardCopy () throws IOException {
77.727 + try {
77.728 + return new PackageTransferable (this, DnDConstants.ACTION_COPY);
77.729 + } catch (ClassNotFoundException e) {
77.730 + throw new AssertionError(e);
77.731 + }
77.732 + }
77.733 +
77.734 + @Override
77.735 + public Transferable clipboardCut () throws IOException {
77.736 + try {
77.737 + return new PackageTransferable (this, DnDConstants.ACTION_MOVE);
77.738 + } catch (ClassNotFoundException e) {
77.739 + throw new AssertionError(e);
77.740 + }
77.741 + }
77.742 +
77.743 + @Override
77.744 + public /*@Override*/ Transferable drag () throws IOException {
77.745 + try {
77.746 + return new PackageTransferable (this, DnDConstants.ACTION_NONE);
77.747 + } catch (ClassNotFoundException e) {
77.748 + throw new AssertionError(e);
77.749 + }
77.750 + }
77.751 +
77.752 + @Override
77.753 + public PasteType[] getPasteTypes(Transferable t) {
77.754 + if (t.isDataFlavorSupported(ExTransferable.multiFlavor)) {
77.755 + try {
77.756 + MultiTransferObject mto = (MultiTransferObject) t.getTransferData (ExTransferable.multiFlavor);
77.757 + boolean hasPackageFlavor = false;
77.758 + for (int i=0; i < mto.getCount(); i++) {
77.759 + DataFlavor[] flavors = mto.getTransferDataFlavors(i);
77.760 + if (isPackageFlavor(flavors)) {
77.761 + hasPackageFlavor = true;
77.762 + }
77.763 + }
77.764 + return hasPackageFlavor ? new PasteType[0] : super.getPasteTypes (t);
77.765 + } catch (UnsupportedFlavorException | IOException e) {
77.766 + ErrorManager.getDefault().notify(e);
77.767 + return new PasteType[0];
77.768 + }
77.769 + }
77.770 + else {
77.771 + DataFlavor[] flavors = t.getTransferDataFlavors();
77.772 + if (isPackageFlavor(flavors)) {
77.773 + return new PasteType[0];
77.774 + }
77.775 + else {
77.776 + return super.getPasteTypes(t);
77.777 + }
77.778 + }
77.779 + }
77.780 +
77.781 + @Override
77.782 + public /*@Override*/ PasteType getDropType (Transferable t, int action, int index) {
77.783 + if (t.isDataFlavorSupported(ExTransferable.multiFlavor)) {
77.784 + try {
77.785 + MultiTransferObject mto = (MultiTransferObject) t.getTransferData (ExTransferable.multiFlavor);
77.786 + boolean hasPackageFlavor = false;
77.787 + for (int i=0; i < mto.getCount(); i++) {
77.788 + DataFlavor[] flavors = mto.getTransferDataFlavors(i);
77.789 + if (isPackageFlavor(flavors)) {
77.790 + hasPackageFlavor = true;
77.791 + }
77.792 + }
77.793 + return hasPackageFlavor ? null : super.getDropType (t, action, index);
77.794 + } catch (UnsupportedFlavorException | IOException e) {
77.795 + ErrorManager.getDefault().notify(e);
77.796 + return null;
77.797 + }
77.798 + }
77.799 + else {
77.800 + DataFlavor[] flavors = t.getTransferDataFlavors();
77.801 + if (isPackageFlavor(flavors)) {
77.802 + return null;
77.803 + }
77.804 + else {
77.805 + return super.getDropType (t, action, index);
77.806 + }
77.807 + }
77.808 + }
77.809 +
77.810 +
77.811 + private boolean isPackageFlavor (DataFlavor[] flavors) {
77.812 + for (int i=0; i<flavors.length; i++) {
77.813 + if (SUBTYPE.equals(flavors[i].getSubType ()) && PRIMARY_TYPE.equals(flavors[i].getPrimaryType ())) {
77.814 + //Disable pasting into package, only paste into root is allowed
77.815 + return true;
77.816 + }
77.817 + }
77.818 + return false;
77.819 + }
77.820 +
77.821 +// TOR
77.822 +// private synchronized PackageRenameHandler getRenameHandler() {
77.823 +// Collection<? extends PackageRenameHandler> handlers = Lookup.getDefault().lookupAll(PackageRenameHandler.class);
77.824 +// if (handlers.size()==0)
77.825 +// return null;
77.826 +// if (handlers.size()>1)
77.827 +// ErrorManager.getDefault().log(ErrorManager.WARNING, "Multiple instances of PackageRenameHandler found in Lookup; only using first one: " + handlers); //NOI18N
77.828 +// return handlers.iterator().next();
77.829 +// }
77.830 +
77.831 + @Override
77.832 + public void setName(String name) {
77.833 +// PackageRenameHandler handler = getRenameHandler();
77.834 +// if (handler!=null) {
77.835 +// handler.handleRename(this, name);
77.836 +// return;
77.837 +// }
77.838 +
77.839 + if (isDefaultPackage) {
77.840 + return;
77.841 + }
77.842 + String oldName = getName();
77.843 + if (oldName.equals(name)) {
77.844 + return;
77.845 + }
77.846 + if (!isValidPackageName (name)) {
77.847 + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message (
77.848 + NbBundle.getMessage(PackageViewChildren.class,"MSG_InvalidPackageName"), NotifyDescriptor.INFORMATION_MESSAGE));
77.849 + return;
77.850 + }
77.851 + name = name.replace('.','/')+'/'; //NOI18N
77.852 + oldName = oldName.replace('.','/')+'/'; //NOI18N
77.853 + int i;
77.854 + for (i=0; i<oldName.length() && i< name.length(); i++) {
77.855 + if (oldName.charAt(i) != name.charAt(i)) {
77.856 + break;
77.857 + }
77.858 + }
77.859 + i--;
77.860 + int index = oldName.lastIndexOf('/',i); //NOI18N
77.861 + String commonPrefix = index == -1 ? null : oldName.substring(0,index);
77.862 + String toCreate = (index+1 == name.length()) ? "" : name.substring(index+1); //NOI18N
77.863 + try {
77.864 + FileObject commonFolder = commonPrefix == null ? this.root : this.root.getFileObject(commonPrefix);
77.865 + FileObject destination = commonFolder;
77.866 + StringTokenizer dtk = new StringTokenizer(toCreate,"/"); //NOI18N
77.867 + while (dtk.hasMoreTokens()) {
77.868 + String pathElement = dtk.nextToken();
77.869 + FileObject tmp = destination.getFileObject(pathElement);
77.870 + if (tmp == null) {
77.871 + tmp = destination.createFolder (pathElement);
77.872 + }
77.873 + destination = tmp;
77.874 + }
77.875 + FileObject source = this.dataFolder.getPrimaryFile();
77.876 + DataFolder sourceFolder = DataFolder.findFolder (source);
77.877 + DataFolder destinationFolder = DataFolder.findFolder (destination);
77.878 + DataObject[] children = sourceFolder.getChildren();
77.879 + for (int j=0; j<children.length; j++) {
77.880 + if (children[j].getPrimaryFile().isData()) {
77.881 + children[j].move(destinationFolder);
77.882 + }
77.883 + }
77.884 + while (!commonFolder.equals(source)) {
77.885 + if (source.getChildren().length==0) {
77.886 + FileObject tmp = source;
77.887 + source = source.getParent();
77.888 + tmp.delete();
77.889 + }
77.890 + else {
77.891 + break;
77.892 + }
77.893 + }
77.894 + } catch (IOException ioe) {
77.895 + ErrorManager.getDefault().notify (ioe);
77.896 + }
77.897 + }
77.898 +
77.899 +
77.900 +
77.901 + @Override
77.902 + public boolean canDestroy() {
77.903 + if ( isDefaultPackage ) {
77.904 + return false;
77.905 + }
77.906 + else {
77.907 + return true;
77.908 + }
77.909 + }
77.910 +
77.911 + @Override
77.912 + public void destroy() throws IOException {
77.913 + FileObject parent = dataFolder.getPrimaryFile().getParent();
77.914 + // First; delete all files except packages
77.915 + DataObject ch[] = dataFolder.getChildren();
77.916 + boolean empty = true;
77.917 + for( int i = 0; ch != null && i < ch.length; i++ ) {
77.918 + if ( !ch[i].getPrimaryFile().isFolder() ) {
77.919 + ch[i].delete();
77.920 + }
77.921 + else {
77.922 + empty = false;
77.923 + }
77.924 + }
77.925 +
77.926 + // If empty delete itself
77.927 + if ( empty ) {
77.928 + super.destroy();
77.929 + }
77.930 +
77.931 +
77.932 + // Second; delete empty super packages
77.933 + while( !parent.equals( root ) && parent.getChildren().length == 0 ) {
77.934 + FileObject newParent = parent.getParent();
77.935 + parent.delete();
77.936 + parent = newParent;
77.937 + }
77.938 + }
77.939 +
77.940 + /**
77.941 + * Initially overridden to support CVS status labels in package nodes.
77.942 + *
77.943 + * @return annotated display name
77.944 + */
77.945 + @Override
77.946 + public String getHtmlDisplayName() {
77.947 + String name = getDisplayName();
77.948 + try {
77.949 + FileObject fo = dataFolder.getPrimaryFile();
77.950 + Set<FileObject> set = new NonRecursiveFolderSet(fo);
77.951 + FileSystem.Status status = fo.getFileSystem().getStatus();
77.952 + if (status instanceof FileSystem.HtmlStatus) {
77.953 + name = ((FileSystem.HtmlStatus) status).annotateNameHtml(name, set);
77.954 + } else {
77.955 + // #89138: return null if the name starts with '<' and status is not HtmlStatus
77.956 + if (name.startsWith("<")) {
77.957 + name = null;
77.958 + } else {
77.959 + name = status.annotateName(name, set);
77.960 + }
77.961 + }
77.962 + } catch (FileStateInvalidException e) {
77.963 + // no fs, do nothing
77.964 + }
77.965 + return name;
77.966 + }
77.967 +
77.968 + @Override
77.969 + public String getDisplayName() {
77.970 + FileObject folder = dataFolder.getPrimaryFile();
77.971 + String path = FileUtil.getRelativePath(root, folder);
77.972 + if (path == null) {
77.973 + // ???
77.974 + return "";
77.975 + }
77.976 + return PackageDisplayUtils.getDisplayLabel( path.replace('/', '.'));
77.977 + }
77.978 +
77.979 + @Override
77.980 + public String getShortDescription() {
77.981 + FileObject folder = dataFolder.getPrimaryFile();
77.982 + String path = FileUtil.getRelativePath(root, folder);
77.983 + if (path == null) {
77.984 + // ???
77.985 + return "";
77.986 + }
77.987 + return PackageDisplayUtils.getToolTip(folder, path.replace('/', '.'));
77.988 + }
77.989 +
77.990 + @Override
77.991 + public Image getIcon (int type) {
77.992 + Image img = getMyIcon (type);
77.993 +
77.994 + try {
77.995 + FileObject fo = dataFolder.getPrimaryFile();
77.996 + Set<FileObject> set = new NonRecursiveFolderSet(fo);
77.997 + img = fo.getFileSystem ().getStatus ().annotateIcon (img, type, set);
77.998 + } catch (FileStateInvalidException e) {
77.999 + // no fs, do nothing
77.1000 + }
77.1001 +
77.1002 + return img;
77.1003 + }
77.1004 +
77.1005 + @Override
77.1006 + public Image getOpenedIcon (int type) {
77.1007 + Image img = getMyOpenedIcon(type);
77.1008 +
77.1009 + try {
77.1010 + FileObject fo = dataFolder.getPrimaryFile();
77.1011 + Set<FileObject> set = new NonRecursiveFolderSet(fo);
77.1012 + img = fo.getFileSystem ().getStatus ().annotateIcon (img, type, set);
77.1013 + } catch (FileStateInvalidException e) {
77.1014 + // no fs, do nothing
77.1015 + }
77.1016 +
77.1017 + return img;
77.1018 + }
77.1019 +
77.1020 +
77.1021 + private Image getMyIcon(int type) {
77.1022 + FileObject folder = dataFolder.getPrimaryFile();
77.1023 + String path = FileUtil.getRelativePath(root, folder);
77.1024 + if (path == null) {
77.1025 + // ??? - #103711: null cannot be returned because the icon
77.1026 + // must be annotated; general package icon is returned instead
77.1027 + return ImageUtilities.loadImage("org/netbeans/modules/python/project/resources/package.gif"); // NOI18N
77.1028 + }
77.1029 + //return PackageDisplayUtils.getIcon(folder, path.replace('/', '.'), isLeaf() );
77.1030 + return PackageDisplayUtils.getIcon(folder, path.replace('/', '.'),
77.1031 + PackageDisplayUtils.isEmpty(dataFolder.getPrimaryFile(), false, true));
77.1032 + }
77.1033 +
77.1034 + private Image getMyOpenedIcon(int type) {
77.1035 + return getMyIcon(type);
77.1036 + }
77.1037 +
77.1038 + public void update() {
77.1039 + fireIconChange();
77.1040 + fireOpenedIconChange();
77.1041 + }
77.1042 +
77.1043 + public void updateDisplayName() {
77.1044 + fireNameChange(null, null);
77.1045 + fireDisplayNameChange(null, null);
77.1046 + fireShortDescriptionChange(null, null);
77.1047 + }
77.1048 +
77.1049 + public void updateChildren() {
77.1050 + boolean leaf = isLeaf();
77.1051 + DataFolder df = getDataFolder();
77.1052 + boolean empty = isEmpty( df );
77.1053 + if ( leaf != empty ) {
77.1054 + setChildren( empty ? Children.LEAF: df.createNodeChildren( NO_FOLDERS_FILTER ) );
77.1055 + update();
77.1056 + }
77.1057 + }
77.1058 +
77.1059 + @Override
77.1060 + public Node.PropertySet[] getPropertySets () {
77.1061 + Node.PropertySet[] properties = super.getPropertySets ();
77.1062 + for (int i=0; i< properties.length; i++) {
77.1063 + if (Sheet.PROPERTIES.equals(properties[i].getName())) {
77.1064 + //Replace the Sheet.PROPERTIES by the new one
77.1065 + //having only the name property which does refactoring
77.1066 + properties[i] = Sheet.createPropertiesSet();
77.1067 + ((Sheet.Set) properties[i]).put(new PropertySupport.ReadWrite<String>(DataObject.PROP_NAME, String.class,
77.1068 + NbBundle.getMessage(PackageViewChildren.class,"PROP_name"), NbBundle.getMessage(PackageViewChildren.class,"HINT_name")) {
77.1069 + @Override
77.1070 + public String getValue() {
77.1071 + return PackageViewChildren.PackageNode.this.getName();
77.1072 + }
77.1073 + @Override
77.1074 + public void setValue(String n) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
77.1075 + if (!canRename()) {
77.1076 + throw new IllegalAccessException();
77.1077 + }
77.1078 + PackageViewChildren.PackageNode.this.setName(n);
77.1079 + }
77.1080 + @Override
77.1081 + public boolean canWrite() {
77.1082 + return PackageViewChildren.PackageNode.this.canRename();
77.1083 + }
77.1084 + });
77.1085 + }
77.1086 + }
77.1087 + return properties;
77.1088 + }
77.1089 +
77.1090 + private DataFolder getDataFolder() {
77.1091 + return getCookie(DataFolder.class);
77.1092 + }
77.1093 +
77.1094 + private boolean isValidPackageName(String name) {
77.1095 + if (name.length() == 0) {
77.1096 + //Fast check of default pkg
77.1097 + return true;
77.1098 + }
77.1099 + StringTokenizer tk = new StringTokenizer(name,".",true); //NOI18N
77.1100 + boolean delimExpected = false;
77.1101 + while (tk.hasMoreTokens()) {
77.1102 + String namePart = tk.nextToken();
77.1103 + if (!delimExpected) {
77.1104 + if (namePart.equals(".")) { //NOI18N
77.1105 + return false;
77.1106 + }
77.1107 + for (int i=0; i< namePart.length(); i++) {
77.1108 + char c = namePart.charAt(i);
77.1109 + if (i == 0) {
77.1110 + if (!Character.isJavaIdentifierStart (c)) {
77.1111 + return false;
77.1112 + }
77.1113 + }
77.1114 + else {
77.1115 + if (!Character.isJavaIdentifierPart(c)) {
77.1116 + return false;
77.1117 + }
77.1118 + }
77.1119 + }
77.1120 + }
77.1121 + else {
77.1122 + if (!namePart.equals(".")) { //NOI18N
77.1123 + return false;
77.1124 + }
77.1125 + }
77.1126 + delimExpected = !delimExpected;
77.1127 + }
77.1128 + return delimExpected;
77.1129 + }
77.1130 + }
77.1131 +
77.1132 + private static final class NoFoldersContainer
77.1133 + implements DataObject.Container, PropertyChangeListener,
77.1134 + NonRecursiveFolder {
77.1135 + private DataFolder folder;
77.1136 + private PropertyChangeSupport prop = new PropertyChangeSupport (this);
77.1137 +
77.1138 + public NoFoldersContainer (DataFolder folder) {
77.1139 + this.folder = folder;
77.1140 + }
77.1141 +
77.1142 + @Override
77.1143 + public FileObject getFolder() {
77.1144 + return folder.getPrimaryFile();
77.1145 + }
77.1146 +
77.1147 + @Override
77.1148 + public DataObject[] getChildren () {
77.1149 + DataObject[] arr = folder.getChildren ();
77.1150 + List<DataObject> list = new ArrayList<>(arr.length);
77.1151 + for (int i = 0; i < arr.length; i++) {
77.1152 + if (arr[i] instanceof DataFolder) continue;
77.1153 +
77.1154 + list.add (arr[i]);
77.1155 + }
77.1156 + return list.size() == arr.length ? arr : list.toArray(new DataObject[0]);
77.1157 + }
77.1158 +
77.1159 + @Override
77.1160 + public void addPropertyChangeListener(PropertyChangeListener l) {
77.1161 + prop.addPropertyChangeListener (l);
77.1162 + }
77.1163 +
77.1164 + @Override
77.1165 + public void removePropertyChangeListener(PropertyChangeListener l) {
77.1166 + prop.removePropertyChangeListener (l);
77.1167 + }
77.1168 +
77.1169 + @Override
77.1170 + public void propertyChange(PropertyChangeEvent evt) {
77.1171 + if (DataObject.Container.PROP_CHILDREN.equals (evt.getPropertyName ())) {
77.1172 + prop.firePropertyChange (PROP_CHILDREN, null, null);
77.1173 + }
77.1174 + }
77.1175 + }
77.1176 +
77.1177 + private final class NoFoldersDataFilter implements ChangeListener, ChangeableDataFilter, DataFilter.FileBased {
77.1178 +
77.1179 + private final ChangeSupport cs = new ChangeSupport(this);
77.1180 +
77.1181 + public NoFoldersDataFilter() {
77.1182 + VisibilityQuery.getDefault().addChangeListener(WeakListeners.change(this, VisibilityQuery.getDefault()));
77.1183 + }
77.1184 +
77.1185 + @Override
77.1186 + public boolean acceptDataObject(DataObject obj) {
77.1187 + // Filter out .pyc or .pyo files!
77.1188 + String ext = obj.getPrimaryFile().getExt();
77.1189 + if ("pyc".equals(ext) || "pyo".equals(ext)) { // NOI18N
77.1190 + return false;
77.1191 + }
77.1192 + return acceptFileObject(obj.getPrimaryFile());
77.1193 + }
77.1194 +
77.1195 + @Override
77.1196 + public void stateChanged( ChangeEvent e) {
77.1197 + cs.fireChange();
77.1198 + }
77.1199 +
77.1200 + @Override
77.1201 + public void addChangeListener( ChangeListener listener ) {
77.1202 + cs.addChangeListener(listener);
77.1203 + }
77.1204 +
77.1205 + @Override
77.1206 + public void removeChangeListener( ChangeListener listener ) {
77.1207 + cs.removeChangeListener(listener);
77.1208 + }
77.1209 +
77.1210 + @Override
77.1211 + public boolean acceptFileObject(FileObject fo) {
77.1212 + return fo.isValid() && VisibilityQuery.getDefault().isVisible(fo) && fo.isData() && group.contains(fo);
77.1213 + }
77.1214 +
77.1215 + }
77.1216 +
77.1217 + static class PackageTransferable extends ExTransferable.Single {
77.1218 +
77.1219 + private PackageNode node;
77.1220 +
77.1221 + public PackageTransferable (PackageNode node, int operation) throws ClassNotFoundException {
77.1222 + super(new DataFlavor(PACKAGE_FLAVOR.format(new Object[] {new Integer(operation)}), null, PackageNode.class.getClassLoader()));
77.1223 + this.node = node;
77.1224 + }
77.1225 +
77.1226 + @Override
77.1227 + protected Object getData() throws IOException, UnsupportedFlavorException {
77.1228 + return this.node;
77.1229 + }
77.1230 + }
77.1231 +
77.1232 +
77.1233 + static class PackagePasteType extends PasteType {
77.1234 +
77.1235 + private int op;
77.1236 + private PackageNode[] nodes;
77.1237 + private FileObject srcRoot;
77.1238 +
77.1239 + public PackagePasteType (FileObject srcRoot, PackageNode[] node, int op) {
77.1240 + assert op == DnDConstants.ACTION_COPY || op == DnDConstants.ACTION_MOVE || op == DnDConstants.ACTION_NONE : "Invalid DnD operation"; //NOI18N
77.1241 + this.nodes = node;
77.1242 + this.op = op;
77.1243 + this.srcRoot = srcRoot;
77.1244 + }
77.1245 +
77.1246 + public void setOperation (int op) {
77.1247 + this.op = op;
77.1248 + }
77.1249 +
77.1250 + @Override
77.1251 + public Transferable paste() throws IOException {
77.1252 + assert this.op != DnDConstants.ACTION_NONE;
77.1253 + for (int ni=0; ni< nodes.length; ni++) {
77.1254 + FileObject fo = srcRoot;
77.1255 + if (!nodes[ni].isDefaultPackage) {
77.1256 + String pkgName = nodes[ni].getName();
77.1257 + StringTokenizer tk = new StringTokenizer(pkgName,"."); //NOI18N
77.1258 + while (tk.hasMoreTokens()) {
77.1259 + String name = tk.nextToken();
77.1260 + FileObject tmp = fo.getFileObject(name,null);
77.1261 + if (tmp == null) {
77.1262 + tmp = fo.createFolder(name);
77.1263 + }
77.1264 + fo = tmp;
77.1265 + }
77.1266 + }
77.1267 + DataFolder dest = DataFolder.findFolder(fo);
77.1268 + DataObject[] children = nodes[ni].dataFolder.getChildren();
77.1269 + boolean cantDelete = false;
77.1270 + for (int i=0; i< children.length; i++) {
77.1271 + if (children[i].getPrimaryFile().isData()
77.1272 + && VisibilityQuery.getDefault().isVisible (children[i].getPrimaryFile())) {
77.1273 + //Copy only the package level
77.1274 + if (this.op == DnDConstants.ACTION_MOVE) {
77.1275 + children[i].move(dest);
77.1276 + }
77.1277 + else {
77.1278 + children[i].copy (dest);
77.1279 + }
77.1280 + }
77.1281 + else {
77.1282 + cantDelete = true;
77.1283 + }
77.1284 + }
77.1285 + if (this.op == DnDConstants.ACTION_MOVE && !cantDelete) {
77.1286 + try {
77.1287 + FileObject tmpFo = nodes[ni].dataFolder.getPrimaryFile();
77.1288 + FileObject originalRoot = nodes[ni].root;
77.1289 + assert tmpFo != null && originalRoot != null;
77.1290 + while (!tmpFo.equals(originalRoot)) {
77.1291 + if (tmpFo.getChildren().length == 0) {
77.1292 + FileObject tmpFoParent = tmpFo.getParent();
77.1293 + tmpFo.delete ();
77.1294 + tmpFo = tmpFoParent;
77.1295 + }
77.1296 + else {
77.1297 + break;
77.1298 + }
77.1299 + }
77.1300 + } catch (IOException ioe) {
77.1301 + //Not important
77.1302 + }
77.1303 + }
77.1304 + }
77.1305 + return ExTransferable.EMPTY;
77.1306 + }
77.1307 +
77.1308 + @Override
77.1309 + public String getName() {
77.1310 + return NbBundle.getMessage(PackageViewChildren.class,"TXT_PastePackage");
77.1311 + }
77.1312 + }
77.1313 +
77.1314 + /**
77.1315 + * FileObject set that represents package. It means
77.1316 + * that it's content must not be processed recursively.
77.1317 + */
77.1318 + private static class NonRecursiveFolderSet extends HashSet<FileObject> implements NonRecursiveFolder {
77.1319 +
77.1320 + private final FileObject folder;
77.1321 +
77.1322 + /**
77.1323 + * Creates set with one element, the folder.
77.1324 + */
77.1325 + public NonRecursiveFolderSet(FileObject folder) {
77.1326 + this.folder = folder;
77.1327 + add(folder);
77.1328 + }
77.1329 +
77.1330 + @Override
77.1331 + public FileObject getFolder() {
77.1332 + return folder;
77.1333 + }
77.1334 + }
77.1335 +}
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/PythonProjectSettings.java Tue Feb 24 01:58:36 2015 -0800
78.3 @@ -0,0 +1,119 @@
78.4 +/*
78.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
78.6 + *
78.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
78.8 + *
78.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
78.10 + * Other names may be trademarks of their respective owners.
78.11 + *
78.12 + * The contents of this file are subject to the terms of either the GNU
78.13 + * General Public License Version 2 only ("GPL") or the Common
78.14 + * Development and Distribution License("CDDL") (collectively, the
78.15 + * "License"). You may not use this file except in compliance with the
78.16 + * License. You can obtain a copy of the License at
78.17 + * http://www.netbeans.org/cddl-gplv2.html
78.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
78.19 + * specific language governing permissions and limitations under the
78.20 + * License. When distributing the software, include this License Header
78.21 + * Notice in each file and include the License file at
78.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
78.23 + * particular file as subject to the "Classpath" exception as provided
78.24 + * by Oracle in the GPL Version 2 section of the License file that
78.25 + * accompanied this code. If applicable, add the following below the
78.26 + * License Header, with the fields enclosed by brackets [] replaced by
78.27 + * your own identifying information:
78.28 + * "Portions Copyrighted [year] [name of copyright owner]"
78.29 + *
78.30 + * Contributor(s):
78.31 + *
78.32 + * The Original Software is NetBeans. The Initial Developer of the Original
78.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
78.34 + * Microsystems, Inc. All Rights Reserved.
78.35 + *
78.36 + * If you wish your version of this file to be governed by only the CDDL
78.37 + * or only the GPL Version 2, indicate your decision by adding
78.38 + * "[Contributor] elects to include this software in this distribution
78.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
78.40 + * single choice of license, a recipient has the option to distribute
78.41 + * your version of this file under either the CDDL, the GPL Version 2 or
78.42 + * to extend the choice of license to its licensees as provided above.
78.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
78.44 + * Version 2 license, then the option applies only if the new code is
78.45 + * made subject to such option by the copyright holder.
78.46 + */
78.47 +
78.48 +package org.netbeans.modules.python.project2.ui;
78.49 +
78.50 +import java.beans.PropertyChangeListener;
78.51 +import java.beans.PropertyChangeSupport;
78.52 +import java.util.prefs.Preferences;
78.53 +import org.openide.util.NbPreferences;
78.54 +
78.55 +/**
78.56 + * Preferences for the module.
78.57 + * <p>
78.58 + * <b>This is copied from the corresponding Java action in java.projects (JavaProjectSettings)</b>
78.59 + * </p>
78.60 + *
78.61 + * @author Tomas Zezula, Jesse Glick
78.62 + */
78.63 +public class PythonProjectSettings {
78.64 +
78.65 + private PythonProjectSettings() {}
78.66 +
78.67 + private static final PropertyChangeSupport pcs = new PropertyChangeSupport(PythonProjectSettings.class);
78.68 +
78.69 + /**
78.70 + * The package view should be displayed as a list of packages.
78.71 + */
78.72 + public static final int TYPE_PACKAGE_VIEW = 0;
78.73 +
78.74 + /**
78.75 + * The package view should be displayed as a tree of folders.
78.76 + */
78.77 + public static final int TYPE_TREE = 1;
78.78 +
78.79 + public static final String PROP_PACKAGE_VIEW_TYPE = "packageViewType"; //NOI18N
78.80 +// private static final String PROP_SHOW_AGAIN_BROKEN_REF_ALERT = "showAgainBrokenRefAlert"; //NOI18N
78.81 +
78.82 + private static Preferences prefs() {
78.83 + return NbPreferences.forModule(PythonProjectSettings.class);
78.84 + }
78.85 +
78.86 + /**
78.87 + * Returns how the package view should be displayed.
78.88 + * @return {@link #TYPE_PACKAGE_VIEW} or {@link #TYPE_TREE}
78.89 + */
78.90 + public static int getPackageViewType() {
78.91 + return prefs().getInt(PROP_PACKAGE_VIEW_TYPE, TYPE_PACKAGE_VIEW);
78.92 + }
78.93 +
78.94 + /**
78.95 + * Sets how the package view should be displayed.
78.96 + * @param type either {@link #TYPE_PACKAGE_VIEW} or {@link #TYPE_TREE}
78.97 + */
78.98 + public static void setPackageViewType(int type) {
78.99 + int currentType = getPackageViewType();
78.100 + if (currentType != type) {
78.101 + prefs().putInt(PROP_PACKAGE_VIEW_TYPE, type);
78.102 + pcs.firePropertyChange(PROP_PACKAGE_VIEW_TYPE, currentType, type);
78.103 + }
78.104 + }
78.105 +
78.106 +// public static boolean isShowAgainBrokenRefAlert() {
78.107 +// return prefs().getBoolean(PROP_SHOW_AGAIN_BROKEN_REF_ALERT, true);
78.108 +// }
78.109 +//
78.110 +// public static void setShowAgainBrokenRefAlert(boolean again) {
78.111 +// prefs().putBoolean(PROP_SHOW_AGAIN_BROKEN_REF_ALERT, again);
78.112 +// }
78.113 +
78.114 + public static void addPropertyChangeListener(PropertyChangeListener l) {
78.115 + pcs.addPropertyChangeListener(l);
78.116 + }
78.117 +
78.118 + public static void removePropertyChangeListener(PropertyChangeListener l) {
78.119 + pcs.removePropertyChangeListener(l);
78.120 + }
78.121 +
78.122 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/SourceNodeFactory.java Tue Feb 24 01:58:36 2015 -0800
79.3 @@ -0,0 +1,257 @@
79.4 +/*
79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
79.6 + *
79.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
79.8 + *
79.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
79.10 + * Other names may be trademarks of their respective owners.
79.11 + *
79.12 + * The contents of this file are subject to the terms of either the GNU
79.13 + * General Public License Version 2 only ("GPL") or the Common
79.14 + * Development and Distribution License("CDDL") (collectively, the
79.15 + * "License"). You may not use this file except in compliance with the
79.16 + * License. You can obtain a copy of the License at
79.17 + * http://www.netbeans.org/cddl-gplv2.html
79.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
79.19 + * specific language governing permissions and limitations under the
79.20 + * License. When distributing the software, include this License Header
79.21 + * Notice in each file and include the License file at
79.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
79.23 + * particular file as subject to the "Classpath" exception as provided
79.24 + * by Oracle in the GPL Version 2 section of the License file that
79.25 + * accompanied this code. If applicable, add the following below the
79.26 + * License Header, with the fields enclosed by brackets [] replaced by
79.27 + * your own identifying information:
79.28 + * "Portions Copyrighted [year] [name of copyright owner]"
79.29 + *
79.30 + * Contributor(s):
79.31 + *
79.32 + * The Original Software is NetBeans. The Initial Developer of the Original
79.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
79.34 + * Microsystems, Inc. All Rights Reserved.
79.35 + *
79.36 + * If you wish your version of this file to be governed by only the CDDL
79.37 + * or only the GPL Version 2, indicate your decision by adding
79.38 + * "[Contributor] elects to include this software in this distribution
79.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
79.40 + * single choice of license, a recipient has the option to distribute
79.41 + * your version of this file under either the CDDL, the GPL Version 2 or
79.42 + * to extend the choice of license to its licensees as provided above.
79.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
79.44 + * Version 2 license, then the option applies only if the new code is
79.45 + * made subject to such option by the copyright holder.
79.46 + */
79.47 +
79.48 +package org.netbeans.modules.python.project2.ui;
79.49 +
79.50 +import java.awt.event.ActionEvent;
79.51 +import java.util.ArrayList;
79.52 +import java.util.Collections;
79.53 +import java.util.List;
79.54 +import javax.swing.AbstractAction;
79.55 +import javax.swing.Action;
79.56 +import javax.swing.SwingUtilities;
79.57 +import javax.swing.event.ChangeEvent;
79.58 +import javax.swing.event.ChangeListener;
79.59 +import org.netbeans.modules.python.project2.PythonProject2;
79.60 +import org.netbeans.api.project.Project;
79.61 +import org.netbeans.api.project.ProjectUtils;
79.62 +import org.netbeans.api.project.SourceGroup;
79.63 +import org.netbeans.api.project.Sources;
79.64 +import org.netbeans.spi.project.ui.support.NodeFactory;
79.65 +import org.netbeans.spi.project.ui.support.NodeList;
79.66 +import org.openide.filesystems.FileObject;
79.67 +import org.openide.nodes.FilterNode;
79.68 +import org.openide.nodes.Node;
79.69 +import org.openide.util.ChangeSupport;
79.70 +import org.openide.util.NbBundle;
79.71 +
79.72 +/**
79.73 + * Source roots view
79.74 + * @author Tomas Zezula
79.75 + */
79.76 +@NbBundle.Messages({"LBL_Properties_Action=Properties"})
79.77 +public final class SourceNodeFactory implements NodeFactory {
79.78 + public SourceNodeFactory() {
79.79 + }
79.80 +
79.81 + @Override
79.82 + public NodeList createNodes(Project p) {
79.83 + PythonProject2 project = (PythonProject2)p.getLookup().lookup(PythonProject2.class);
79.84 + assert project != null;
79.85 + return new SourcesNodeList(project);
79.86 + }
79.87 +
79.88 + private static class SourcesNodeList implements NodeList<SourceGroupKey>, ChangeListener {
79.89 +
79.90 + private PythonProject2 project;
79.91 +
79.92 + private final ChangeSupport changeSupport = new ChangeSupport(this);
79.93 +
79.94 + public SourcesNodeList(PythonProject2 proj) {
79.95 + project = proj;
79.96 + }
79.97 +
79.98 + @Override
79.99 + public List<SourceGroupKey> keys() {
79.100 + if (this.project.getProjectDirectory() == null || !this.project.getProjectDirectory().isValid()) {
79.101 + return Collections.EMPTY_LIST;
79.102 + }
79.103 + Sources sources = getSources();
79.104 + SourceGroup[] groups = sources.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON);
79.105 +
79.106 + List result = new ArrayList(groups.length);
79.107 + for (SourceGroup group : groups) {
79.108 + result.add(new SourceGroupKey(group));
79.109 + }
79.110 + return result;
79.111 + }
79.112 +
79.113 + @Override
79.114 + public void addChangeListener(ChangeListener l) {
79.115 + changeSupport.addChangeListener(l);
79.116 + }
79.117 +
79.118 + @Override
79.119 + public void removeChangeListener(ChangeListener l) {
79.120 + changeSupport.removeChangeListener(l);
79.121 + }
79.122 +
79.123 + @Override
79.124 + public Node node(SourceGroupKey key) {
79.125 + return new PackageViewFilterNode(key.group, project);
79.126 + }
79.127 +
79.128 + @Override
79.129 + public void addNotify() {
79.130 + getSources().addChangeListener(this);
79.131 + }
79.132 +
79.133 + @Override
79.134 + public void removeNotify() {
79.135 + getSources().removeChangeListener(this);
79.136 + }
79.137 +
79.138 + @Override
79.139 + public void stateChanged(ChangeEvent e) {
79.140 + // setKeys(getKeys());
79.141 + // The caller holds ProjectManager.mutex() read lock
79.142 + SwingUtilities.invokeLater(new Runnable() {
79.143 + @Override
79.144 + public void run() {
79.145 + changeSupport.fireChange();
79.146 + }
79.147 + });
79.148 + }
79.149 +
79.150 + private Sources getSources() {
79.151 + return ProjectUtils.getSources(project);
79.152 + }
79.153 +
79.154 + }
79.155 +
79.156 + private static class SourceGroupKey {
79.157 +
79.158 + public final SourceGroup group;
79.159 + public final FileObject fileObject;
79.160 +
79.161 + SourceGroupKey(SourceGroup group) {
79.162 + this.group = group;
79.163 + this.fileObject = group.getRootFolder();
79.164 + }
79.165 +
79.166 + @Override
79.167 + public int hashCode() {
79.168 + int hash = 5;
79.169 + String disp = this.group.getDisplayName();
79.170 + hash = 79 * hash + (fileObject != null ? fileObject.hashCode() : 0);
79.171 + hash = 79 * hash + (disp != null ? disp.hashCode() : 0);
79.172 + return hash;
79.173 + }
79.174 +
79.175 + @Override
79.176 + public boolean equals(Object obj) {
79.177 + if (!(obj instanceof SourceGroupKey)) {
79.178 + return false;
79.179 + } else {
79.180 + SourceGroupKey otherKey = (SourceGroupKey) obj;
79.181 +
79.182 + if (fileObject != otherKey.fileObject && (fileObject == null || !fileObject.equals(otherKey.fileObject))) {
79.183 + return false;
79.184 + }
79.185 + String thisDisplayName = this.group.getDisplayName();
79.186 + String otherDisplayName = otherKey.group.getDisplayName();
79.187 + boolean oneNull = thisDisplayName == null;
79.188 + boolean twoNull = otherDisplayName == null;
79.189 + return !(oneNull != twoNull || !thisDisplayName.equals(otherDisplayName));
79.190 + }
79.191 + }
79.192 +
79.193 +
79.194 + }
79.195 +
79.196 + /** Yet another cool filter node just to add properties action
79.197 + */
79.198 + private static class PackageViewFilterNode extends FilterNode {
79.199 +
79.200 + private String nodeName;
79.201 + private Project project;
79.202 +
79.203 + Action[] actions;
79.204 +
79.205 + public PackageViewFilterNode(SourceGroup sourceGroup, Project project) {
79.206 + super(PackageView.createPackageView(sourceGroup));
79.207 + this.project = project;
79.208 + this.nodeName = "Sources"; //NOI18N
79.209 + }
79.210 +
79.211 + @Override
79.212 + public Action[] getActions(boolean context) {
79.213 + if (!context) {
79.214 + if (actions == null) {
79.215 + Action superActions[] = super.getActions(context);
79.216 + actions = new Action[superActions.length + 2];
79.217 + System.arraycopy(superActions, 0, actions, 0, superActions.length);
79.218 + actions[superActions.length] = null;
79.219 + actions[superActions.length + 1] = new PreselectPropertiesAction(project, nodeName);
79.220 + }
79.221 + return actions;
79.222 + } else {
79.223 + return super.getActions(context);
79.224 + }
79.225 + }
79.226 +
79.227 + }
79.228 +
79.229 +
79.230 + /** The special properties action
79.231 + */
79.232 + static class PreselectPropertiesAction extends AbstractAction {
79.233 +
79.234 + private final Project project;
79.235 + private final String nodeName;
79.236 + private final String panelName;
79.237 +
79.238 + public PreselectPropertiesAction(Project project, String nodeName) {
79.239 + this(project, nodeName, null);
79.240 + }
79.241 +
79.242 + public PreselectPropertiesAction(Project project, String nodeName, String panelName) {
79.243 + super(NbBundle.getMessage(SourceNodeFactory.class, "LBL_Properties_Action"));
79.244 + this.project = project;
79.245 + this.nodeName = nodeName;
79.246 + this.panelName = panelName;
79.247 + }
79.248 +
79.249 + @Override
79.250 + public void actionPerformed(ActionEvent e) {
79.251 +//todo: Add customizer
79.252 +// CustomizerProviderImpl cp = (CustomizerProviderImpl) project.getLookup().lookup(CustomizerProviderImpl.class);
79.253 +// if (cp != null) {
79.254 +// cp.showCustomizer(nodeName, panelName);
79.255 +// }
79.256 +
79.257 + }
79.258 + }
79.259 +
79.260 +}
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/TreeRootNode.java Tue Feb 24 01:58:36 2015 -0800
80.3 @@ -0,0 +1,312 @@
80.4 +/*
80.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
80.6 + *
80.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
80.8 + *
80.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
80.10 + * Other names may be trademarks of their respective owners.
80.11 + *
80.12 + * The contents of this file are subject to the terms of either the GNU
80.13 + * General Public License Version 2 only ("GPL") or the Common
80.14 + * Development and Distribution License("CDDL") (collectively, the
80.15 + * "License"). You may not use this file except in compliance with the
80.16 + * License. You can obtain a copy of the License at
80.17 + * http://www.netbeans.org/cddl-gplv2.html
80.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
80.19 + * specific language governing permissions and limitations under the
80.20 + * License. When distributing the software, include this License Header
80.21 + * Notice in each file and include the License file at
80.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
80.23 + * particular file as subject to the "Classpath" exception as provided
80.24 + * by Oracle in the GPL Version 2 section of the License file that
80.25 + * accompanied this code. If applicable, add the following below the
80.26 + * License Header, with the fields enclosed by brackets [] replaced by
80.27 + * your own identifying information:
80.28 + * "Portions Copyrighted [year] [name of copyright owner]"
80.29 + *
80.30 + * Contributor(s):
80.31 + *
80.32 + * The Original Software is NetBeans. The Initial Developer of the Original
80.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
80.34 + * Microsystems, Inc. All Rights Reserved.
80.35 + *
80.36 + * If you wish your version of this file to be governed by only the CDDL
80.37 + * or only the GPL Version 2, indicate your decision by adding
80.38 + * "[Contributor] elects to include this software in this distribution
80.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
80.40 + * single choice of license, a recipient has the option to distribute
80.41 + * your version of this file under either the CDDL, the GPL Version 2 or
80.42 + * to extend the choice of license to its licensees as provided above.
80.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
80.44 + * Version 2 license, then the option applies only if the new code is
80.45 + * made subject to such option by the copyright holder.
80.46 + */
80.47 +package org.netbeans.modules.python.project2.ui;
80.48 +
80.49 +import java.awt.EventQueue;
80.50 +import java.awt.Image;
80.51 +import java.beans.PropertyChangeEvent;
80.52 +import java.beans.PropertyChangeListener;
80.53 +import java.util.ArrayList;
80.54 +import java.util.Collections;
80.55 +import java.util.List;
80.56 +import java.util.StringTokenizer;
80.57 +import java.util.logging.Level;
80.58 +import java.util.logging.Logger;
80.59 +import javax.swing.Icon;
80.60 +import javax.swing.event.ChangeEvent;
80.61 +import javax.swing.event.ChangeListener;
80.62 +import javax.swing.event.EventListenerList;
80.63 +import org.netbeans.api.project.SourceGroup;
80.64 +import org.netbeans.api.queries.VisibilityQuery;
80.65 +import org.openide.DialogDisplayer;
80.66 +import org.openide.NotifyDescriptor;
80.67 +import org.openide.filesystems.FileObject;
80.68 +import org.openide.filesystems.FileUtil;
80.69 +import org.openide.loaders.ChangeableDataFilter;
80.70 +import org.openide.loaders.DataFolder;
80.71 +import org.openide.loaders.DataObject;
80.72 +import org.openide.nodes.FilterNode;
80.73 +import org.openide.nodes.Node;
80.74 +import org.openide.nodes.NodeNotFoundException;
80.75 +import org.openide.nodes.NodeOp;
80.76 +import org.openide.util.ImageUtilities;
80.77 +import org.openide.util.NbBundle;
80.78 +import org.openide.util.Utilities;
80.79 +import org.openide.util.WeakListeners;
80.80 +import org.openide.util.lookup.Lookups;
80.81 +import org.openide.util.lookup.ProxyLookup;
80.82 +
80.83 +/**
80.84 + * Copied from java.project API module, the same copy is in ruby project, rails project, etc.
80.85 + * Unlike PackageViewChildren this class definitelly requires more generic API module, probably projectui.
80.86 + * Displays a package root in a tree.
80.87 + * @see "#42151"
80.88 + * @author Jesse Glick
80.89 + */
80.90 +public final class TreeRootNode extends FilterNode implements PropertyChangeListener {
80.91 +
80.92 + private final static Image SOURCE_ROOT_BADGE = ImageUtilities.loadImage("org/netbeans/modules/python/project2/resources/sourceBadge.gif"); // NOI18N
80.93 + private final SourceGroup g;
80.94 +
80.95 + public TreeRootNode(SourceGroup g) {
80.96 + this(DataFolder.findFolder(g.getRootFolder()), g);
80.97 + }
80.98 +
80.99 + private TreeRootNode(DataFolder folder, SourceGroup g) {
80.100 + this(new FilterNode(folder.getNodeDelegate(), folder.createNodeChildren(new VisibilityQueryDataFilter(g))), g);
80.101 + }
80.102 +
80.103 + @SuppressWarnings("LeakingThisInConstructor")
80.104 + private TreeRootNode(Node originalNode, SourceGroup g) {
80.105 + super(originalNode, new PackageFilterChildren(originalNode),
80.106 + new ProxyLookup(
80.107 + originalNode.getLookup(),
80.108 + Lookups.singleton(new PathFinder(g)) // no need for explicit search info
80.109 + ));
80.110 + this.g = g;
80.111 + g.addPropertyChangeListener(WeakListeners.propertyChange(this, g));
80.112 + }
80.113 +
80.114 + /** Copied from PackageRootNode with modifications. */
80.115 + private Image computeIcon(boolean opened, int type) {
80.116 + Icon icon = g.getIcon(opened);
80.117 + if (icon == null) {
80.118 + Image image = opened ? super.getOpenedIcon(type) : super.getIcon(type);
80.119 + return ImageUtilities.mergeImages(image, SOURCE_ROOT_BADGE, 7, 7);
80.120 + } else {
80.121 + return ImageUtilities.icon2Image(icon);
80.122 + }
80.123 + }
80.124 +
80.125 + @Override
80.126 + public Image getIcon(int type) {
80.127 + return computeIcon(false, type);
80.128 + }
80.129 +
80.130 + @Override
80.131 + public Image getOpenedIcon(int type) {
80.132 + return computeIcon(true, type);
80.133 + }
80.134 +
80.135 + @Override
80.136 + public String getName() {
80.137 + return g.getName();
80.138 + }
80.139 +
80.140 + @Override
80.141 + public String getDisplayName() {
80.142 + return g.getDisplayName();
80.143 + }
80.144 +
80.145 + @Override
80.146 + public boolean canRename() {
80.147 + return false;
80.148 + }
80.149 +
80.150 + @Override
80.151 + public boolean canDestroy() {
80.152 + return false;
80.153 + }
80.154 +
80.155 + @Override
80.156 + public boolean canCut() {
80.157 + return false;
80.158 + }
80.159 +
80.160 + @Override
80.161 + public void propertyChange(PropertyChangeEvent ev) {
80.162 + // XXX handle SourceGroup.rootFolder change too
80.163 + EventQueue.invokeLater(new Runnable() {
80.164 +
80.165 + @Override
80.166 + public void run() {
80.167 + fireNameChange(null, null);
80.168 + fireDisplayNameChange(null, null);
80.169 + fireIconChange();
80.170 + fireOpenedIconChange();
80.171 + }
80.172 + });
80.173 + }
80.174 +
80.175 + /** Copied from PhysicalView and PackageRootNode. */
80.176 + public static final class PathFinder {
80.177 +
80.178 + private final SourceGroup g;
80.179 +
80.180 + PathFinder(SourceGroup g) {
80.181 + this.g = g;
80.182 + }
80.183 +
80.184 + public Node findPath(Node rootNode, Object o) {
80.185 + FileObject fo;
80.186 + if (o instanceof FileObject) {
80.187 + fo = (FileObject) o;
80.188 + } else if (o instanceof DataObject) {
80.189 + fo = ((DataObject) o).getPrimaryFile();
80.190 + } else {
80.191 + return null;
80.192 + }
80.193 + FileObject groupRoot = g.getRootFolder();
80.194 + if (FileUtil.isParentOf(groupRoot, fo) /* && group.contains(fo) */) {
80.195 + FileObject folder = fo.isFolder() ? fo : fo.getParent();
80.196 + String relPath = FileUtil.getRelativePath(groupRoot, folder);
80.197 + List<String> path = new ArrayList<>();
80.198 + StringTokenizer strtok = new StringTokenizer(relPath, "/"); // NOI18N
80.199 + while (strtok.hasMoreTokens()) {
80.200 + String token = strtok.nextToken();
80.201 + path.add(token);
80.202 + }
80.203 + try {
80.204 + Node folderNode = folder.equals(groupRoot) ? rootNode : NodeOp.findPath(rootNode, Collections.enumeration(path));
80.205 + if (fo.isFolder()) {
80.206 + return folderNode;
80.207 + } else {
80.208 + Node[] childs = folderNode.getChildren().getNodes(true);
80.209 + for (Node child : childs) {
80.210 + DataObject dobj = child.getLookup().lookup(DataObject.class);
80.211 + if (dobj != null && dobj.getPrimaryFile().getNameExt().equals(fo.getNameExt())) {
80.212 + return child;
80.213 + }
80.214 + }
80.215 + }
80.216 + } catch (NodeNotFoundException e) {
80.217 + LOG.log(Level.WARNING, "TreeRootNode.findPath", e);
80.218 + }
80.219 + } else if (groupRoot.equals(fo)) {
80.220 + return rootNode;
80.221 + }
80.222 + return null;
80.223 + }
80.224 + private static final Logger LOG = Logger.getLogger(PathFinder.class.getName());
80.225 + }
80.226 +
80.227 + private static final class VisibilityQueryDataFilter implements ChangeListener, PropertyChangeListener, ChangeableDataFilter {
80.228 +
80.229 + private static final long serialVersionUID = 1L; // in case a DataFolder.ClonedFilterHandle saves me
80.230 + private final EventListenerList ell = new EventListenerList();
80.231 + private final SourceGroup g;
80.232 +
80.233 + @SuppressWarnings("LeakingThisInConstructor")
80.234 + public VisibilityQueryDataFilter(SourceGroup g) {
80.235 + this.g = g;
80.236 + VisibilityQuery.getDefault().addChangeListener(WeakListeners.change(this, VisibilityQuery.getDefault()));
80.237 + g.addPropertyChangeListener(WeakListeners.propertyChange(this, g));
80.238 + }
80.239 +
80.240 + @Override
80.241 + public boolean acceptDataObject(DataObject obj) {
80.242 + FileObject fo = obj.getPrimaryFile();
80.243 + if (fo.getExt().equalsIgnoreCase("pyc") || fo.getExt().equalsIgnoreCase("pyo") | fo.getExt().equalsIgnoreCase("egg-info") || fo.getName().equalsIgnoreCase("build") || fo.getName().equalsIgnoreCase("dist")) {
80.244 + return false;
80.245 + }
80.246 + return g.contains(fo) &&
80.247 + VisibilityQuery.getDefault().isVisible(fo);
80.248 + }
80.249 +
80.250 + @Override
80.251 + public void stateChanged(ChangeEvent e) {
80.252 + fireChange();
80.253 + }
80.254 +
80.255 + @Override
80.256 + public void propertyChange(PropertyChangeEvent e) {
80.257 + if (SourceGroup.PROP_CONTAINERSHIP.equals(e.getPropertyName())) {
80.258 + fireChange();
80.259 + }
80.260 + }
80.261 +
80.262 + private void fireChange() {
80.263 + Object[] listeners = ell.getListenerList();
80.264 + ChangeEvent event = null;
80.265 + for (int i = listeners.length - 2; i >= 0; i -= 2) {
80.266 + if (listeners[i] == ChangeListener.class) {
80.267 + if (event == null) {
80.268 + event = new ChangeEvent(this);
80.269 + }
80.270 + ((ChangeListener) listeners[i + 1]).stateChanged(event);
80.271 + }
80.272 + }
80.273 + }
80.274 +
80.275 + @Override
80.276 + public void addChangeListener(ChangeListener listener) {
80.277 + ell.add(ChangeListener.class, listener);
80.278 + }
80.279 +
80.280 + @Override
80.281 + public void removeChangeListener(ChangeListener listener) {
80.282 + ell.remove(ChangeListener.class, listener);
80.283 + }
80.284 + }
80.285 +
80.286 + private static final class PackageFilterChildren extends FilterNode.Children {
80.287 +
80.288 + public PackageFilterChildren(final Node originalNode) {
80.289 + super(originalNode);
80.290 + }
80.291 +
80.292 + @Override
80.293 + protected Node copyNode(final Node originalNode) {
80.294 + DataObject dobj = originalNode.getLookup().lookup(DataObject.class);
80.295 + return (dobj instanceof DataFolder) ? new PackageFilterNode(originalNode) : super.copyNode(originalNode);
80.296 + }
80.297 + }
80.298 +
80.299 + private static final class PackageFilterNode extends FilterNode {
80.300 +
80.301 + public PackageFilterNode(final Node origNode) {
80.302 + super(origNode, new PackageFilterChildren(origNode));
80.303 + }
80.304 +
80.305 + @Override
80.306 + public void setName(final String name) {
80.307 + if (Utilities.isJavaIdentifier(name)) {
80.308 + super.setName(name);
80.309 + } else {
80.310 + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
80.311 + NbBundle.getMessage(TreeRootNode.class, "MSG_InvalidPackageName"), NotifyDescriptor.INFORMATION_MESSAGE));
80.312 + }
80.313 + }
80.314 + }
80.315 +}
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/Utils.java Tue Feb 24 01:58:36 2015 -0800
81.3 @@ -0,0 +1,166 @@
81.4 +package org.netbeans.modules.python.project2.ui;
81.5 +
81.6 +import java.awt.Component;
81.7 +import java.io.File;
81.8 +import java.util.Iterator;
81.9 +import java.util.List;
81.10 +import javax.swing.ComboBoxModel;
81.11 +import javax.swing.DefaultComboBoxModel;
81.12 +import javax.swing.JButton;
81.13 +import javax.swing.JComponent;
81.14 +import javax.swing.JFileChooser;
81.15 +import javax.swing.JList;
81.16 +import javax.swing.JTable;
81.17 +import javax.swing.ListCellRenderer;
81.18 +import javax.swing.table.DefaultTableCellRenderer;
81.19 +import javax.swing.table.DefaultTableModel;
81.20 +import javax.swing.table.TableModel;
81.21 +import org.netbeans.modules.python.api.PythonPlatform;
81.22 +import org.netbeans.modules.python.api.PythonPlatformManager;
81.23 +import org.netbeans.modules.python.project2.PythonProject2;
81.24 +import org.openide.DialogDescriptor;
81.25 +import org.openide.DialogDisplayer;
81.26 +import org.openide.awt.HtmlRenderer;
81.27 +import org.openide.filesystems.FileObject;
81.28 +import org.openide.filesystems.FileUtil;
81.29 +import org.openide.util.HelpCtx;
81.30 +import org.openide.util.NbBundle;
81.31 +import org.openide.util.Pair;
81.32 +
81.33 +/**
81.34 + *
81.35 + * @author Tomas Zezula
81.36 + */
81.37 +public class Utils {
81.38 +
81.39 + @NbBundle.Messages({"LBL_SelectMainModule=Select Main Module", "LBL_BrowseMainModules=Browse Main Modules"})
81.40 + public static String chooseMainModule (PythonProject2 project) {
81.41 + final JButton okButton = new JButton (NbBundle.getMessage(Utils.class, "LBL_SelectMainModule"));
81.42 + final MainModuleChooser mcc = new MainModuleChooser(project, okButton);
81.43 + final Object[] options = new Object[] {okButton, DialogDescriptor.CANCEL_OPTION};
81.44 + final DialogDescriptor dd = new DialogDescriptor (mcc, NbBundle.getMessage(Utils.class, "LBL_BrowseMainModules"), true, options,
81.45 + okButton,DialogDescriptor.RIGHT_ALIGN,HelpCtx.DEFAULT_HELP,null);
81.46 + dd.setClosingOptions(options);
81.47 + if (DialogDisplayer.getDefault().notify(dd) == okButton) {
81.48 + return mcc.getMainModule();
81.49 + }
81.50 + return null;
81.51 + }
81.52 +
81.53 + public static interface SourceRootsMediator {
81.54 + public void setRelatedEditMediator(SourceRootsMediator rem);
81.55 + }
81.56 +
81.57 + public static ComboBoxModel createPlatformModel () {
81.58 + return new PlatformModel ();
81.59 + }
81.60 +
81.61 + public static ListCellRenderer createPlatformRenderer () {
81.62 + return new PlatformRenderer();
81.63 + }
81.64 +
81.65 + private static class PlatformModel extends DefaultComboBoxModel {
81.66 +
81.67 + private final PythonPlatformManager manager;
81.68 +
81.69 + public PlatformModel () {
81.70 + manager = PythonPlatformManager.getInstance();
81.71 + init ();
81.72 + }
81.73 +
81.74 + private void init () {
81.75 + this.removeAllElements(); //init will be used also in case of chnge of installed plaforms
81.76 + final List<String> ids = manager.getPlatformList();
81.77 + for (String id : ids) {
81.78 + PythonPlatform platform = manager.getPlatform(id);
81.79 + this.addElement(platform);
81.80 + }
81.81 + }
81.82 + }
81.83 +
81.84 + private static class PlatformRenderer implements ListCellRenderer {
81.85 +
81.86 + private final ListCellRenderer delegate;
81.87 +
81.88 + public PlatformRenderer () {
81.89 + delegate = HtmlRenderer.createRenderer();
81.90 + }
81.91 +
81.92 + @Override
81.93 + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
81.94 + String name;
81.95 + if (value instanceof PythonPlatform) {
81.96 + PythonPlatform key = (PythonPlatform) value;
81.97 + name = key.getName();
81.98 + }
81.99 + else if (value instanceof String) {
81.100 + //hndles broken platform for customizer
81.101 + name = "<html><font color=\"#A40000\">" //NOI18N
81.102 + + NbBundle.getMessage(
81.103 + Utils.class, "TXT_BrokenPlatformFmt", (String)value);
81.104 + }
81.105 + else {
81.106 + name = "";
81.107 + }
81.108 + return delegate.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
81.109 + }
81.110 +
81.111 + }
81.112 +
81.113 + private static class SourceRootsModel extends DefaultTableModel {
81.114 +
81.115 + public SourceRootsModel (Object[][] data) {
81.116 + super (data,new Object[]{"location","label"});//NOI18N
81.117 + }
81.118 +
81.119 + @Override
81.120 + public boolean isCellEditable(int row, int column) {
81.121 + return column == 1;
81.122 + }
81.123 +
81.124 + @Override
81.125 + public Class getColumnClass(int columnIndex) {
81.126 + switch (columnIndex) {
81.127 + case 0:
81.128 + return File.class;
81.129 + case 1:
81.130 + return String.class;
81.131 + default:
81.132 + return super.getColumnClass (columnIndex);
81.133 + }
81.134 + }
81.135 + }
81.136 +
81.137 + private static class FileRenderer extends DefaultTableCellRenderer {
81.138 +
81.139 + private File projectFolder;
81.140 +
81.141 + public FileRenderer (File projectFolder) {
81.142 + this.projectFolder = projectFolder;
81.143 + }
81.144 +
81.145 + @Override
81.146 + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row, int column) {
81.147 + String displayName;
81.148 + if (value instanceof File) {
81.149 + File root = (File) value;
81.150 + String pfPath = projectFolder.getAbsolutePath() + File.separatorChar;
81.151 + String srPath = root.getAbsolutePath();
81.152 + if (srPath.startsWith(pfPath)) {
81.153 + displayName = srPath.substring(pfPath.length());
81.154 + }
81.155 + else {
81.156 + displayName = srPath;
81.157 + }
81.158 + }
81.159 + else {
81.160 + displayName = null;
81.161 + }
81.162 + Component c = super.getTableCellRendererComponent(table, displayName, isSelected, hasFocus, row, column);
81.163 + if (c instanceof JComponent) {
81.164 + ((JComponent) c).setToolTipText (displayName);
81.165 + }
81.166 + return c;
81.167 + }
81.168 + }
81.169 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/actions/Command.java Tue Feb 24 01:58:36 2015 -0800
82.3 @@ -0,0 +1,116 @@
82.4 +/*
82.5 + * To change this template, choose Tools | Templates
82.6 + * and open the template in the editor.
82.7 + */
82.8 +package org.netbeans.modules.python.project2.ui.actions;
82.9 +
82.10 +import java.io.File;
82.11 +import java.util.ArrayList;
82.12 +import javax.swing.JOptionPane;
82.13 +import org.netbeans.api.project.ProjectUtils;
82.14 +import org.netbeans.api.project.SourceGroup;
82.15 +import org.netbeans.api.project.Sources;
82.16 +import org.netbeans.modules.python.api.PythonPlatform;
82.17 +import org.netbeans.modules.python.api.PythonPlatformManager;
82.18 +import org.netbeans.modules.python.project2.PythonProject2;
82.19 +import org.openide.filesystems.FileUtil;
82.20 +import org.openide.nodes.Node;
82.21 +import org.openide.util.Lookup;
82.22 +import org.openide.windows.TopComponent;
82.23 +
82.24 +/**
82.25 + * @author Radek Matous
82.26 + * @author Tomas Zezula
82.27 + */
82.28 +public abstract class Command {
82.29 +
82.30 + private final PythonProject2 project;
82.31 +
82.32 + public Command(PythonProject2 project) {
82.33 + this.project = project;
82.34 + assert project != null;
82.35 + }
82.36 +
82.37 + public abstract String getCommandId();
82.38 +
82.39 + public abstract void invokeAction(Lookup context) throws IllegalArgumentException;
82.40 +
82.41 + public abstract boolean isActionEnabled(Lookup context) throws IllegalArgumentException;
82.42 +
82.43 + public boolean asyncCallRequired() {
82.44 + return true;
82.45 + }
82.46 +
82.47 + public boolean saveRequired() {
82.48 + return true;
82.49 + }
82.50 +
82.51 + public final PythonProject2 getProject() {
82.52 + return project;
82.53 + }
82.54 +
82.55 + public Node[] getSelectedNodes() {
82.56 + return TopComponent.getRegistry().getCurrentNodes();
82.57 + }
82.58 +
82.59 + protected void showLaunchError(String message) {
82.60 + JOptionPane.showMessageDialog(null, message, "Python Launch Error", JOptionPane.ERROR_MESSAGE);
82.61 +
82.62 + }
82.63 +
82.64 + /**
82.65 + * used by children to handle sever launched errors
82.66 + *
82.67 + * @param errMessage
82.68 + */
82.69 + protected PythonPlatform checkProjectPythonPlatform(PythonProject2 pyProject) {
82.70 +// PythonPlatform platform = PythonProject2Util.getActivePlatform(pyProject);
82.71 +// if ( platform == null ) {
82.72 +// // Better to inform the user than try to use a default unsuited
82.73 +// String platformId = pyProject.getEvaluator().getProperty(PythonProject2Properties.ACTIVE_PLATFORM);
82.74 +// showLaunchError( "selected project has broken python platform : " +
82.75 +// platformId +
82.76 +// " => bind to an existing python platform in project's properties "
82.77 +// );
82.78 +// }
82.79 + PythonPlatform platform = PythonPlatformManager.getInstance().getPlatforms().get(0);
82.80 + return platform;
82.81 + }
82.82 +
82.83 + /**
82.84 + *
82.85 + * provide a reasonable common Build of PYTHONPATH for Run or Debug commands
82.86 + *
82.87 + * @param platform current platform
82.88 + * @param project current project
82.89 + * @return PythonPath FileList
82.90 + */
82.91 + protected ArrayList<String> buildPythonPath(PythonPlatform platform, PythonProject2 project) {
82.92 + final ArrayList<String> pythonPath = new ArrayList<String>();
82.93 + // start with platform
82.94 + pythonPath.addAll(platform.getPythonPath());
82.95 + Sources sources = ProjectUtils.getSources(project);
82.96 + for (SourceGroup fo : sources.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON)) {
82.97 + File f = FileUtil.toFile(fo.getRootFolder());
82.98 + pythonPath.add(f.getAbsolutePath());
82.99 + }
82.100 + return pythonPath;
82.101 + }
82.102 +
82.103 + /**
82.104 + *
82.105 + * provide a reasonable common Build of JAVAPATH for Run or Debug Jython
82.106 + * commands
82.107 + *
82.108 + * @param platform current platform
82.109 + * @param project current project
82.110 + * @return JavaPath fileList for jython CLASSPATH command
82.111 + */
82.112 +// protected ArrayList<String> buildJavaPath( PythonPlatform platform , PythonProject2 project ) {
82.113 +// final ArrayList<String> javaPath = new ArrayList<String>() ;
82.114 +// // start with platform
82.115 +// javaPath.addAll(platform.getJavaPath());
82.116 +// javaPath.addAll(getProperties().getJavaPath());
82.117 +// return javaPath ;
82.118 +// }
82.119 +}
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/actions/RunCommand.java Tue Feb 24 01:58:36 2015 -0800
83.3 @@ -0,0 +1,137 @@
83.4 +package org.netbeans.modules.python.project2.ui.actions;
83.5 +
83.6 +import org.netbeans.modules.python.api.PythonExecution;
83.7 +import org.netbeans.modules.python.api.PythonPlatform;
83.8 +import org.netbeans.modules.python.project2.PythonProject2;
83.9 +import org.netbeans.api.project.ProjectUtils;
83.10 +import org.netbeans.api.project.SourceGroup;
83.11 +import org.netbeans.api.project.Sources;
83.12 +import org.netbeans.modules.python.project2.ui.Utils;
83.13 +import org.netbeans.spi.project.ActionProvider;
83.14 +import org.openide.filesystems.FileObject;
83.15 +import org.openide.filesystems.FileUtil;
83.16 +import org.openide.util.Lookup;
83.17 +
83.18 +/**
83.19 + *
83.20 + * @author alley
83.21 + */
83.22 +public class RunCommand extends Command {
83.23 +
83.24 + protected final boolean isTest;
83.25 +
83.26 + public RunCommand(PythonProject2 project, boolean isTest) {
83.27 + super(project);
83.28 + this.isTest = isTest;
83.29 + }
83.30 +
83.31 + @Override
83.32 + public String getCommandId() {
83.33 + return isTest ? ActionProvider.COMMAND_TEST : ActionProvider.COMMAND_RUN;
83.34 + }
83.35 +
83.36 + @Override
83.37 + public void invokeAction(Lookup context) throws IllegalArgumentException {
83.38 +// if (isTest) {
83.39 +// TestRunner testRunner = PythonActionProvider.getTestRunner(TestRunner.TestType.PY_UNIT);
83.40 +// //boolean testTaskExist = RakeSupport.getRakeTask(project, TEST_TASK_NAME) != null;
83.41 +// //if (testTaskExist) {
83.42 +// // File pwd = FileUtil.toFile(project.getProjectDirectory());
83.43 +// // RakeRunner runner = new RakeRunner(project);
83.44 +// // runner.setPWD(pwd);
83.45 +// // runner.setFileLocator(new RubyFileLocator(context, project));
83.46 +// // runner.showWarnings(true);
83.47 +// // runner.setDebug(COMMAND_DEBUG_SINGLE.equals(command));
83.48 +// // runner.run(TEST_TASK_NAME);
83.49 +// //} else if (testRunner != null) {
83.50 +// testRunner.getInstance().runAllTests(getProject(), false);
83.51 +// //}
83.52 +// return;
83.53 +// }
83.54 +
83.55 + final PythonProject2 pyProject = getProject();
83.56 + final PythonPlatform platform = checkProjectPythonPlatform(pyProject);
83.57 + if (platform == null) {
83.58 + return; // invalid platform user has been warn in check so safe to return
83.59 + }
83.60 +
83.61 + String main = pyProject.getMainModule();
83.62 + if (main == null || main.isEmpty()) {
83.63 + main = Utils.chooseMainModule(pyProject);
83.64 + pyProject.setMainModule(main);
83.65 + }
83.66 + //System.out.println("main module " + getProperties().getMainModule());
83.67 + FileObject script = findMainFile(pyProject, main);
83.68 + //assert script != null;
83.69 + if (script == null) {
83.70 + main = Utils.chooseMainModule(pyProject);
83.71 + pyProject.setMainModule(main);
83.72 + script = findMainFile(pyProject, main);
83.73 + }
83.74 + if(script == null) {
83.75 + return;
83.76 + }
83.77 + final FileObject parent = script.getParent();
83.78 + PythonExecution pyexec = new PythonExecution();
83.79 + pyexec.setDisplayName(ProjectUtils.getInformation(pyProject).getDisplayName());
83.80 + //Set work dir - probably we need a property to store work dir
83.81 + String path = FileUtil.toFile(parent).getAbsolutePath();
83.82 + pyexec.setWorkingDirectory(path);
83.83 + pyexec.setCommand(platform.getInterpreterCommand());
83.84 + //Set python script
83.85 + path = FileUtil.toFile(script).getAbsolutePath();
83.86 + pyexec.setScript(path);
83.87 + pyexec.setCommandArgs(platform.getInterpreterArgs());
83.88 + pyexec.setScriptArgs(pyProject.getApplicationArgs());
83.89 + //build path & set
83.90 + //build path & set
83.91 + pyexec.setPath(PythonPlatform.buildPath(super.buildPythonPath(platform, pyProject)));
83.92 +// pyexec.setJavaPath(PythonPlatform.buildPath(super.buildJavaPath(platform, pyProject)));
83.93 + pyexec.setShowControls(true);
83.94 + pyexec.setShowInput(true);
83.95 + pyexec.setShowWindow(true);
83.96 + pyexec.addStandardRecognizers();
83.97 +
83.98 +// PythonCoverageProvider coverageProvider = PythonCoverageProvider.get(pyProject);
83.99 +// if (coverageProvider != null && coverageProvider.isEnabled()) {
83.100 +// pyexec = coverageProvider.wrapWithCoverage(pyexec);
83.101 +// }
83.102 +
83.103 + pyexec.run();
83.104 + }
83.105 +
83.106 +
83.107 + @Override
83.108 + public boolean isActionEnabled(Lookup context) throws IllegalArgumentException {
83.109 +// final PythonProject2 pyProject = getProject();
83.110 +// PythonPlatform platform = PythonProject2Util.getActivePlatform(pyProject);
83.111 +// if (platform == null) {
83.112 +// return false;
83.113 +// }
83.114 +// else{
83.115 +// return true;
83.116 +// }
83.117 +// final FileObject fo = findMainFile (pyProject);
83.118 +// if (fo == null) {
83.119 +// return false;
83.120 +// }
83.121 +// return PythonMIMEResolver.PYTHON_MIME_TYPE.equals(fo.getMIMEType());
83.122 + return true;
83.123 + }
83.124 +
83.125 + protected static FileObject findMainFile(final PythonProject2 pyProject, final String mainFile) {
83.126 + if (mainFile == null) {
83.127 + return null;
83.128 + }
83.129 + final Sources sources = ProjectUtils.getSources(pyProject);
83.130 + FileObject fo = null;
83.131 + for (SourceGroup root : sources.getSourceGroups(PythonProject2.SOURCES_TYPE_PYTHON)) {
83.132 + fo = root.getRootFolder().getFileObject(mainFile);
83.133 + if (fo != null) {
83.134 + break;
83.135 + }
83.136 + }
83.137 + return fo;
83.138 + }
83.139 +
83.140 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/actions/RunSingleCommand.java Tue Feb 24 01:58:36 2015 -0800
84.3 @@ -0,0 +1,127 @@
84.4 +package org.netbeans.modules.python.project2.ui.actions;
84.5 +
84.6 +import javax.swing.JOptionPane;
84.7 +import org.netbeans.modules.python.api.PythonExecution;
84.8 +import org.netbeans.modules.python.api.PythonMIMEResolver;
84.9 +import org.netbeans.modules.python.api.PythonOptions;
84.10 +import org.netbeans.modules.python.api.PythonPlatform;
84.11 +import org.netbeans.modules.python.api.PythonPlatformManager;
84.12 +import org.netbeans.modules.python.editor.codecoverage.PythonCoverageProvider;
84.13 +import org.netbeans.modules.python.project2.PythonProject2;
84.14 +import org.netbeans.spi.project.ActionProvider;
84.15 +import org.openide.filesystems.FileObject;
84.16 +import org.openide.filesystems.FileUtil;
84.17 +import org.openide.loaders.DataObject;
84.18 +import org.openide.nodes.Node;
84.19 +import org.openide.util.Lookup;
84.20 +
84.21 +/**
84.22 + *
84.23 + * @author alley
84.24 + */
84.25 +public class RunSingleCommand extends Command {
84.26 +
84.27 + PythonPlatformManager manager = PythonPlatformManager.getInstance();
84.28 + protected boolean isTest;
84.29 +
84.30 + public RunSingleCommand(PythonProject2 project, boolean isTest) {
84.31 + super(project);
84.32 + this.isTest = isTest;
84.33 + }
84.34 +
84.35 + @Override
84.36 + public String getCommandId() {
84.37 + return isTest ? ActionProvider.COMMAND_TEST_SINGLE : ActionProvider.COMMAND_RUN_SINGLE;
84.38 + }
84.39 +
84.40 + @Override
84.41 + public void invokeAction(Lookup context) throws IllegalArgumentException {
84.42 + Node[] activatedNodes = getSelectedNodes();
84.43 + DataObject gdo = activatedNodes[0].getLookup().lookup(DataObject.class);
84.44 + FileObject file = gdo.getPrimaryFile();
84.45 + if (file.getMIMEType().equals(PythonMIMEResolver.PYTHON_MIME_TYPE)) {
84.46 + String path = FileUtil.toFile(file.getParent()).getAbsolutePath();
84.47 + // String workingdir = FileUtil.toFile(getProject().getSrcFolder()).getAbsolutePath();
84.48 + //int pos = path.lastIndexOf("/");
84.49 + //path = path.substring(0, pos);
84.50 + String script = FileUtil.toFile(file).getAbsolutePath();
84.51 + //System.out.println("Folder " + path);
84.52 + //System.out.println("File " + script);
84.53 +
84.54 + final PythonProject2 pyProject = getProject();
84.55 +
84.56 + //String target = FileUtil.getRelativePath(getRoot(project.getSourceRoots().getRoots(),file), file);
84.57 +// if (isTest || file.getName().endsWith("_test")) { // NOI18N
84.58 +//
84.59 +// // See if this looks like a test file; if not, see if we can find its corresponding
84.60 +// // test
84.61 +// boolean isTestFile = (file.getName().endsWith("_test"));
84.62 +// if (!isTestFile) {
84.63 +// for (FileObject testRoot : pyProject.getTestSourceRootFiles()) {
84.64 +// if (FileUtil.isParentOf(testRoot, file)) {
84.65 +// isTestFile = true;
84.66 +// break;
84.67 +// }
84.68 +// }
84.69 +// }
84.70 +// if (!isTestFile) {
84.71 +// // Try to find the matching test
84.72 +// LocationResult result = new GotoTest().findTest(file, -1);
84.73 +// if (result != null && result.getFileObject() != null) {
84.74 +// file = result.getFileObject();
84.75 +// }
84.76 +// }
84.77 +//
84.78 +// // Run test normally - don't pop up browser
84.79 +// TestRunner testRunner = PythonActionProvider.getTestRunner(TestRunner.TestType.PY_UNIT);
84.80 +// if (testRunner != null) {
84.81 +// testRunner.getInstance().runTest(file, false);
84.82 +// return;
84.83 +// }
84.84 +// }
84.85 + PythonExecution pyexec = new PythonExecution();
84.86 + pyexec.setDisplayName(gdo.getName());
84.87 + pyexec.setWorkingDirectory(path);
84.88 + if (PythonOptions.getInstance().getPromptForArgs()) {
84.89 + String args = JOptionPane.showInputDialog("Enter the args for this script.", "");
84.90 + pyexec.setScriptArgs(args);
84.91 +
84.92 + }
84.93 + final PythonPlatform platform = checkProjectPythonPlatform(pyProject);
84.94 + if (platform == null) {
84.95 + return; // invalid platform user has been warn in check so safe to return
84.96 + }
84.97 + pyexec.setCommand(platform.getInterpreterCommand());
84.98 + pyexec.setScript(script);
84.99 + pyexec.setCommandArgs(platform.getInterpreterArgs());
84.100 + pyexec.setPath(PythonPlatform.buildPath(super.buildPythonPath(platform, pyProject)));
84.101 +// pyexec.setJavaPath(PythonPlatform.buildPath(super.buildJavaPath(platform, pyProject)));
84.102 + pyexec.setShowControls(true);
84.103 + pyexec.setShowInput(true);
84.104 + pyexec.setShowWindow(true);
84.105 + pyexec.addStandardRecognizers();
84.106 +
84.107 +// PythonCoverageProvider coverageProvider = PythonCoverageProvider.get(pyProject);
84.108 +// if (coverageProvider != null && coverageProvider.isEnabled()) {
84.109 +// pyexec = coverageProvider.wrapWithCoverage(pyexec);
84.110 +// }
84.111 +
84.112 + pyexec.run();
84.113 + }
84.114 + }
84.115 +
84.116 + @Override
84.117 + public boolean isActionEnabled(Lookup context) throws IllegalArgumentException {
84.118 + boolean results = false; //super.enable(activatedNodes);
84.119 + Node[] activatedNodes = getSelectedNodes();
84.120 + if (activatedNodes != null && activatedNodes.length > 0) {
84.121 + DataObject gdo = activatedNodes[0].getLookup().lookup(DataObject.class);
84.122 + if (gdo != null && gdo.getPrimaryFile() != null) {
84.123 + results = gdo.getPrimaryFile().getMIMEType().equals(
84.124 + PythonMIMEResolver.PYTHON_MIME_TYPE);
84.125 + }
84.126 + }
84.127 + return results;
84.128 + }
84.129 +
84.130 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/Bundle.properties Tue Feb 24 01:58:36 2015 -0800
85.3 @@ -0,0 +1,64 @@
85.4 +# To change this template, choose Tools | Templates
85.5 +# and open the template in the editor.
85.6 +
85.7 +#PythonProjectProperties
85.8 +LBL_Customizer_Title=Project Properties - {0}
85.9 +
85.10 +#CompositePanelProviderImpl
85.11 +LBL_Config_RunConfig=Run
85.12 +LBL_Config_PhpIncludePath=Python
85.13 +
85.14 +#Customizer Sources
85.15 +CTL_ProjectFolder=Project Folder\:
85.16 +MNE_ProjectFolder=F
85.17 +CTL_SourceRoots=Source Root Folders\:
85.18 +MNE_SourceRoots=S
85.19 +CTL_TestRoots=Test Root Folders:
85.20 +MNE_TestRoots=T
85.21 +TXT_Encoding=&Encoding\:
85.22 +CTL_AddSourceRoot=Add Folder...
85.23 +MNE_AddSourceRoot=A
85.24 +CTL_RemoveSourceRoot=Remove
85.25 +MNE_RemoveSourceRoot=R
85.26 +CTL_UpSourceRoot=Move Up
85.27 +MNE_UpSourceRoot=U
85.28 +CTL_DownSourceRoot=Move Down
85.29 +MNE_DownSourceRoot=D
85.30 +CTL_AddTestRoot=Add Folder...
85.31 +MNE_AddTestRoot=o
85.32 +CTL_RemoveTestRoot=Remove
85.33 +MNE_RemoveTestRoot=m
85.34 +CTL_UpTestRoot=Move Up
85.35 +MNE_UpTestRoot=p
85.36 +CTL_DownTestRoot=Move Down
85.37 +MNE_DownTestRoot=w
85.38 +AD_CustomizerSources_addSourceRoot=N/A
85.39 +AD_CustomizerSources_testRoots=N/A
85.40 +AD_CustomizerSources_sourceRoots=N/A
85.41 +AD_CustomizerSources_downTestRoot=N/A
85.42 +AD_CustomizerSources_upTestRoot=N/A
85.43 +AD_CustomizerSources_removeTestRoot=N/A
85.44 +AD_CustomizerSources_addTestRoot=N/A
85.45 +AD_CustomizerSources_downSourceRoot=N/A
85.46 +AD_CustomizerSources_upSourceRoot=N/A
85.47 +AD_CustomizerSources_removeSourceRoot=N/A
85.48 +AD_CustomizerSources_projectLocation=N/A
85.49 +AD_CustomizerSources_Encoding=N/A
85.50 +MSG_EncodingWarning=Changing project encoding might result in some characters in existing files not being read and written correctly.
85.51 +CustomizerRun.mainModule.text=&Main Module:
85.52 +CustomizerRun.mainModule.ad=N/A
85.53 +CustomizerRun.appArgs.text=&Application Arguments:
85.54 +CustomizerRun.appArgs.ad=N/A
85.55 +CustomizerRun.browseMain.text=&Browse...
85.56 +CustomizerRun.browseMain.ad=N/A
85.57 +CustomizerPythonPath.addPythonPath.text=Add...
85.58 +CustomizerPythonPath.moveDownPythonPath.text=Move Down
85.59 +CustomizerPythonPath.moveUpPythonPath.text=Move Up
85.60 +CustomizerPythonPath.removePythonPath.text=Remove
85.61 +CustomizerPythonPath.addPythonPath.text_1=Add...
85.62 +CustomizerPythonPath.moveDownPythonPath.text_1=Move Down
85.63 +CustomizerPythonPath.moveUpPythonPath.text_1=Move Up
85.64 +CustomizerPythonPath.removePythonPath.text_1=Remove
85.65 +CustomizerPythonPath.manage.text=Manage...
85.66 +CustomizerPythonPath.jLabel1.text=Python Platform:
85.67 +CustomizerPythonPath.jLabel2.text=Python Path:
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/CompositePanelProviderImpl.java Tue Feb 24 01:58:36 2015 -0800
86.3 @@ -0,0 +1,67 @@
86.4 +package org.netbeans.modules.python.project2.ui.customizer;
86.5 +
86.6 +import javax.swing.JComponent;
86.7 +import javax.swing.JPanel;
86.8 +import org.netbeans.modules.python.project2.PythonProject2;
86.9 +import org.netbeans.spi.project.ui.support.ProjectCustomizer;
86.10 +import org.netbeans.spi.project.ui.support.ProjectCustomizer.CompositeCategoryProvider;
86.11 +import org.openide.util.Lookup;
86.12 +import org.openide.util.NbBundle;
86.13 +
86.14 +/**
86.15 + *
86.16 + * @author Tomas Zezula
86.17 + */
86.18 +public class CompositePanelProviderImpl implements CompositeCategoryProvider {
86.19 +
86.20 + private static final String PYTHON_PATH = "PythonPath"; //NOI18N
86.21 + private static final String RUN = "Run"; // NOI18N
86.22 +
86.23 + private final String name;
86.24 +
86.25 + public CompositePanelProviderImpl(String name) {
86.26 + this.name = name;
86.27 + }
86.28 +
86.29 + @Override
86.30 + public ProjectCustomizer.Category createCategory(Lookup context) {
86.31 + ProjectCustomizer.Category toReturn = null;
86.32 + final ProjectCustomizer.Category[] categories = null;
86.33 + if (RUN.equals(name)) {
86.34 + toReturn = ProjectCustomizer.Category.create(
86.35 + RUN,
86.36 + NbBundle.getMessage(CompositePanelProviderImpl.class, "LBL_Config_RunConfig"),
86.37 + null,
86.38 + categories);
86.39 + } else if (PYTHON_PATH.equals(name)) {
86.40 + toReturn = ProjectCustomizer.Category.create(
86.41 + PYTHON_PATH,
86.42 + NbBundle.getMessage(CompositePanelProviderImpl.class, "LBL_Config_PhpIncludePath"),
86.43 + null,
86.44 + categories);
86.45 + }
86.46 + assert toReturn != null : "No category for name: " + name;
86.47 + return toReturn;
86.48 + }
86.49 +
86.50 + @Override
86.51 + public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) {
86.52 + String nm = category.getName();
86.53 + PythonProject2 project = context.lookup(PythonProject2.class);
86.54 + if (RUN.equals(nm)) {
86.55 + return new CustomizerRun(project);
86.56 + } else if (PYTHON_PATH.equals(nm)) {
86.57 + return new CustomizerPythonPath(project);
86.58 + }
86.59 + return new JPanel();
86.60 + }
86.61 +
86.62 + public static CompositePanelProviderImpl createRunConfig() {
86.63 + return new CompositePanelProviderImpl(RUN);
86.64 + }
86.65 +
86.66 + public static CompositePanelProviderImpl createPythonPath() {
86.67 + return new CompositePanelProviderImpl(PYTHON_PATH);
86.68 + }
86.69 +
86.70 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/CustomizerPythonPath.form Tue Feb 24 01:58:36 2015 -0800
87.3 @@ -0,0 +1,168 @@
87.4 +<?xml version="1.0" encoding="UTF-8" ?>
87.5 +
87.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
87.7 + <AuxValues>
87.8 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
87.9 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
87.10 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
87.11 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
87.12 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
87.13 + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
87.14 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
87.15 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
87.16 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
87.17 + </AuxValues>
87.18 +
87.19 + <Layout>
87.20 + <DimensionLayout dim="0">
87.21 + <Group type="103" groupAlignment="0" attributes="0">
87.22 + <Group type="102" attributes="0">
87.23 + <EmptySpace max="-2" attributes="0"/>
87.24 + <Group type="103" groupAlignment="0" attributes="0">
87.25 + <Group type="102" alignment="0" attributes="0">
87.26 + <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
87.27 + <EmptySpace max="-2" attributes="0"/>
87.28 + <Component id="platforms" pref="205" max="32767" attributes="0"/>
87.29 + <EmptySpace min="-2" max="-2" attributes="0"/>
87.30 + <Component id="manage" min="-2" max="-2" attributes="0"/>
87.31 + <EmptySpace min="30" pref="30" max="30" attributes="0"/>
87.32 + </Group>
87.33 + <Group type="102" alignment="1" attributes="0">
87.34 + <Component id="jScrollPane2" pref="0" max="32767" attributes="0"/>
87.35 + <EmptySpace max="-2" attributes="0"/>
87.36 + <Group type="103" groupAlignment="0" attributes="0">
87.37 + <Component id="moveDownPythonPath" linkSize="1" alignment="0" min="-2" max="-2" attributes="0"/>
87.38 + <Component id="moveUpPythonPath" linkSize="1" alignment="0" min="-2" max="-2" attributes="1"/>
87.39 + <Component id="removePythonPath" linkSize="1" alignment="0" min="-2" max="-2" attributes="1"/>
87.40 + <Component id="addPythonPath" linkSize="1" alignment="0" min="-2" max="-2" attributes="1"/>
87.41 + </Group>
87.42 + </Group>
87.43 + <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
87.44 + </Group>
87.45 + <EmptySpace min="-2" max="-2" attributes="0"/>
87.46 + </Group>
87.47 + </Group>
87.48 + </DimensionLayout>
87.49 + <DimensionLayout dim="1">
87.50 + <Group type="103" groupAlignment="0" attributes="0">
87.51 + <Group type="102" alignment="0" attributes="0">
87.52 + <EmptySpace min="-2" max="-2" attributes="0"/>
87.53 + <Group type="103" groupAlignment="0" max="-2" attributes="0">
87.54 + <Group type="103" alignment="0" groupAlignment="3" attributes="0">
87.55 + <Component id="platforms" alignment="3" min="-2" max="-2" attributes="0"/>
87.56 + <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
87.57 + </Group>
87.58 + <Component id="manage" alignment="0" min="-2" max="-2" attributes="0"/>
87.59 + </Group>
87.60 + <EmptySpace min="-2" max="-2" attributes="0"/>
87.61 + <Component id="jLabel2" min="-2" pref="16" max="-2" attributes="0"/>
87.62 + <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
87.63 + <Group type="103" groupAlignment="0" attributes="0">
87.64 + <Group type="102" attributes="0">
87.65 + <Component id="addPythonPath" min="-2" max="-2" attributes="0"/>
87.66 + <EmptySpace max="-2" attributes="0"/>
87.67 + <Component id="removePythonPath" min="-2" max="-2" attributes="0"/>
87.68 + <EmptySpace max="-2" attributes="0"/>
87.69 + <Component id="moveUpPythonPath" min="-2" max="-2" attributes="0"/>
87.70 + <EmptySpace max="-2" attributes="0"/>
87.71 + <Component id="moveDownPythonPath" min="-2" max="-2" attributes="0"/>
87.72 + </Group>
87.73 + <Component id="jScrollPane2" pref="214" max="32767" attributes="0"/>
87.74 + </Group>
87.75 + <EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
87.76 + </Group>
87.77 + </Group>
87.78 + </DimensionLayout>
87.79 + </Layout>
87.80 + <SubComponents>
87.81 + <Container class="javax.swing.JScrollPane" name="jScrollPane2">
87.82 + <AuxValues>
87.83 + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
87.84 + </AuxValues>
87.85 +
87.86 + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
87.87 + <SubComponents>
87.88 + <Component class="javax.swing.JList" name="pythonPath">
87.89 + <Properties>
87.90 + <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
87.91 + <Connection code="pythonPathModel" type="code"/>
87.92 + </Property>
87.93 + <Property name="selectionMode" type="int" value="0"/>
87.94 + </Properties>
87.95 + </Component>
87.96 + </SubComponents>
87.97 + </Container>
87.98 + <Component class="javax.swing.JButton" name="addPythonPath">
87.99 + <Properties>
87.100 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.101 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.addPythonPath.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.102 + </Property>
87.103 + </Properties>
87.104 + <Events>
87.105 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addPythonPathActionPerformed"/>
87.106 + </Events>
87.107 + </Component>
87.108 + <Component class="javax.swing.JButton" name="removePythonPath">
87.109 + <Properties>
87.110 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.111 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.removePythonPath.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.112 + </Property>
87.113 + </Properties>
87.114 + <Events>
87.115 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removePythonPathActionPerformed"/>
87.116 + </Events>
87.117 + </Component>
87.118 + <Component class="javax.swing.JButton" name="moveUpPythonPath">
87.119 + <Properties>
87.120 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.121 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.moveUpPythonPath.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.122 + </Property>
87.123 + </Properties>
87.124 + <Events>
87.125 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="moveUpPythonPathActionPerformed"/>
87.126 + </Events>
87.127 + </Component>
87.128 + <Component class="javax.swing.JButton" name="moveDownPythonPath">
87.129 + <Properties>
87.130 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.131 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.moveDownPythonPath.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.132 + </Property>
87.133 + </Properties>
87.134 + <Events>
87.135 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="moveDownPythonPathActionPerformed"/>
87.136 + </Events>
87.137 + </Component>
87.138 + <Component class="javax.swing.JButton" name="manage">
87.139 + <Properties>
87.140 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.141 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.manage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.142 + </Property>
87.143 + </Properties>
87.144 + <Events>
87.145 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="manageActionPerformed"/>
87.146 + </Events>
87.147 + </Component>
87.148 + <Component class="javax.swing.JComboBox" name="platforms">
87.149 + <Events>
87.150 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="platformsActionPerformed"/>
87.151 + </Events>
87.152 + <AuxValues>
87.153 + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="org.netbeans.modules.python.api.PlatformComponentFactory.getPythonPlatformsComboxBox()"/>
87.154 + </AuxValues>
87.155 + </Component>
87.156 + <Component class="javax.swing.JLabel" name="jLabel1">
87.157 + <Properties>
87.158 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.159 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.160 + </Property>
87.161 + </Properties>
87.162 + </Component>
87.163 + <Component class="javax.swing.JLabel" name="jLabel2">
87.164 + <Properties>
87.165 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
87.166 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerPythonPath.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
87.167 + </Property>
87.168 + </Properties>
87.169 + </Component>
87.170 + </SubComponents>
87.171 +</Form>
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/CustomizerPythonPath.java Tue Feb 24 01:58:36 2015 -0800
88.3 @@ -0,0 +1,271 @@
88.4 +/*
88.5 + * To change this template, choose Tools | Templates
88.6 + * and open the template in the editor.
88.7 + */
88.8 +
88.9 +/*
88.10 + * CustomizerPythonPath.java
88.11 + *
88.12 + * Created on Sep 7, 2008, 6:56:16 PM
88.13 + */
88.14 +package org.netbeans.modules.python.project2.ui.customizer;
88.15 +
88.16 +import java.io.File;
88.17 +import java.io.IOException;
88.18 +import javax.swing.JFileChooser;
88.19 +
88.20 +import org.netbeans.modules.python.api.PlatformComponentFactory;
88.21 +import org.netbeans.modules.python.api.PythonPlatform;
88.22 +import org.netbeans.modules.python.core.ui.models.PathListModel;
88.23 +import org.netbeans.modules.python.project2.PythonProject2;
88.24 +import org.netbeans.modules.python.project2.ui.Utils;
88.25 +
88.26 +import org.openide.filesystems.FileObject;
88.27 +import org.openide.filesystems.FileUtil;
88.28 +import org.openide.loaders.DataObject;
88.29 +import org.openide.loaders.InstanceDataObject;
88.30 +import org.openide.util.Exceptions;
88.31 +import org.openide.util.actions.CallableSystemAction;
88.32 +
88.33 +/**
88.34 + *
88.35 + * @author alley
88.36 + */
88.37 +public class CustomizerPythonPath extends javax.swing.JPanel {
88.38 +
88.39 + private final PythonProject2 project;
88.40 + private PlatformComponentFactory.PlatformChangeListener platformListener;
88.41 + private final PathListModel pythonPathModel = new PathListModel();
88.42 +
88.43 + /**
88.44 + * Creates new form CustomizerPythonPath
88.45 + */
88.46 + public CustomizerPythonPath(PythonProject2 properties) {
88.47 + this.project = properties;
88.48 + initComponents();
88.49 +// pythonPathModel.setModel(project.getPythonPath());
88.50 +
88.51 + final PythonPlatform activePlatform = project.getActivePlatform();
88.52 + if (activePlatform != null) {
88.53 + platforms.setSelectedItem(activePlatform);
88.54 + }
88.55 + }
88.56 +
88.57 + public @Override
88.58 + void addNotify() {
88.59 + super.addNotify();
88.60 + platformListener = new PlatformComponentFactory.PlatformChangeListener() {
88.61 + @Override
88.62 + public void platformChanged() {
88.63 + PythonPlatform platform = (PythonPlatform) platforms.getSelectedItem();
88.64 + if (platform != null) {
88.65 + project.setActivePlatform(platform);
88.66 + // When we support configurations:
88.67 + //configs.get(getSelectedConfig()).put(PythonProjectProperties.ACTIVE_PLATFORM, platform.getName());
88.68 + }
88.69 + }
88.70 + };
88.71 + PlatformComponentFactory.addPlatformChangeListener(platforms, platformListener);
88.72 + }
88.73 +
88.74 + public @Override
88.75 + void removeNotify() {
88.76 + PlatformComponentFactory.removePlatformChangeListener(platforms, platformListener);
88.77 + super.removeNotify();
88.78 + }
88.79 +
88.80 + /**
88.81 + * This method is called from within the constructor to initialize the form.
88.82 + * WARNING: Do NOT modify this code. The content of this method is always
88.83 + * regenerated by the Form Editor.
88.84 + */
88.85 + @SuppressWarnings("unchecked")
88.86 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
88.87 + private void initComponents() {
88.88 +
88.89 + jScrollPane2 = new javax.swing.JScrollPane();
88.90 + pythonPath = new javax.swing.JList();
88.91 + addPythonPath = new javax.swing.JButton();
88.92 + removePythonPath = new javax.swing.JButton();
88.93 + moveUpPythonPath = new javax.swing.JButton();
88.94 + moveDownPythonPath = new javax.swing.JButton();
88.95 + manage = new javax.swing.JButton();
88.96 + platforms = org.netbeans.modules.python.api.PlatformComponentFactory.getPythonPlatformsComboxBox();
88.97 + jLabel1 = new javax.swing.JLabel();
88.98 + jLabel2 = new javax.swing.JLabel();
88.99 +
88.100 + pythonPath.setModel(pythonPathModel);
88.101 + pythonPath.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
88.102 + jScrollPane2.setViewportView(pythonPath);
88.103 +
88.104 + addPythonPath.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.addPythonPath.text_1")); // NOI18N
88.105 + addPythonPath.addActionListener(new java.awt.event.ActionListener() {
88.106 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.107 + addPythonPathActionPerformed(evt);
88.108 + }
88.109 + });
88.110 +
88.111 + removePythonPath.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.removePythonPath.text_1")); // NOI18N
88.112 + removePythonPath.addActionListener(new java.awt.event.ActionListener() {
88.113 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.114 + removePythonPathActionPerformed(evt);
88.115 + }
88.116 + });
88.117 +
88.118 + moveUpPythonPath.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.moveUpPythonPath.text_1")); // NOI18N
88.119 + moveUpPythonPath.addActionListener(new java.awt.event.ActionListener() {
88.120 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.121 + moveUpPythonPathActionPerformed(evt);
88.122 + }
88.123 + });
88.124 +
88.125 + moveDownPythonPath.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.moveDownPythonPath.text_1")); // NOI18N
88.126 + moveDownPythonPath.addActionListener(new java.awt.event.ActionListener() {
88.127 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.128 + moveDownPythonPathActionPerformed(evt);
88.129 + }
88.130 + });
88.131 +
88.132 + manage.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.manage.text")); // NOI18N
88.133 + manage.addActionListener(new java.awt.event.ActionListener() {
88.134 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.135 + manageActionPerformed(evt);
88.136 + }
88.137 + });
88.138 +
88.139 + platforms.addActionListener(new java.awt.event.ActionListener() {
88.140 + public void actionPerformed(java.awt.event.ActionEvent evt) {
88.141 + platformsActionPerformed(evt);
88.142 + }
88.143 + });
88.144 +
88.145 + jLabel1.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.jLabel1.text")); // NOI18N
88.146 +
88.147 + jLabel2.setText(org.openide.util.NbBundle.getMessage(CustomizerPythonPath.class, "CustomizerPythonPath.jLabel2.text")); // NOI18N
88.148 +
88.149 + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
88.150 + this.setLayout(layout);
88.151 + layout.setHorizontalGroup(
88.152 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
88.153 + .addGroup(layout.createSequentialGroup()
88.154 + .addContainerGap()
88.155 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
88.156 + .addGroup(layout.createSequentialGroup()
88.157 + .addComponent(jLabel1)
88.158 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.159 + .addComponent(platforms, 0, 205, Short.MAX_VALUE)
88.160 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.161 + .addComponent(manage)
88.162 + .addGap(30, 30, 30))
88.163 + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
88.164 + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
88.165 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.166 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
88.167 + .addComponent(moveDownPythonPath)
88.168 + .addComponent(moveUpPythonPath)
88.169 + .addComponent(removePythonPath)
88.170 + .addComponent(addPythonPath)))
88.171 + .addComponent(jLabel2))
88.172 + .addContainerGap())
88.173 + );
88.174 +
88.175 + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {addPythonPath, moveDownPythonPath, moveUpPythonPath, removePythonPath});
88.176 +
88.177 + layout.setVerticalGroup(
88.178 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
88.179 + .addGroup(layout.createSequentialGroup()
88.180 + .addContainerGap()
88.181 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
88.182 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
88.183 + .addComponent(platforms, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
88.184 + .addComponent(jLabel1))
88.185 + .addComponent(manage))
88.186 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.187 + .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
88.188 + .addGap(8, 8, 8)
88.189 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
88.190 + .addGroup(layout.createSequentialGroup()
88.191 + .addComponent(addPythonPath)
88.192 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.193 + .addComponent(removePythonPath)
88.194 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.195 + .addComponent(moveUpPythonPath)
88.196 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
88.197 + .addComponent(moveDownPythonPath))
88.198 + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 214, Short.MAX_VALUE))
88.199 + .addGap(19, 19, 19))
88.200 + );
88.201 + }// </editor-fold>//GEN-END:initComponents
88.202 +
88.203 + private void addPythonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPythonPathActionPerformed
88.204 + final JFileChooser fc = new JFileChooser();
88.205 + fc.setFileHidingEnabled(false);
88.206 + fc.setDialogTitle("Select Python Egg or Python Lib Directory");
88.207 + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
88.208 + /* jean-Yves for practical reasons @@@ ENHANCE to have multiple selection enabled here */
88.209 + fc.setMultiSelectionEnabled(true);
88.210 + int returnVal = fc.showOpenDialog(this);
88.211 + if (returnVal == JFileChooser.APPROVE_OPTION) {
88.212 + File[] files = fc.getSelectedFiles();
88.213 + for (File file : files) {
88.214 + String cmd = file.getAbsolutePath();
88.215 + pythonPathModel.add(cmd);
88.216 + }
88.217 + }
88.218 +
88.219 +}//GEN-LAST:event_addPythonPathActionPerformed
88.220 +
88.221 + private void removePythonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removePythonPathActionPerformed
88.222 + int selectedIndex = pythonPath.getSelectedIndex();
88.223 + if (selectedIndex != -1) {
88.224 + pythonPathModel.remove(selectedIndex);
88.225 + }
88.226 +}//GEN-LAST:event_removePythonPathActionPerformed
88.227 +
88.228 + private void moveUpPythonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpPythonPathActionPerformed
88.229 + int selectedIndex = pythonPath.getSelectedIndex();
88.230 + if (selectedIndex != -1) {
88.231 + pythonPathModel.moveUp(selectedIndex);
88.232 + }
88.233 +}//GEN-LAST:event_moveUpPythonPathActionPerformed
88.234 +
88.235 + private void moveDownPythonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownPythonPathActionPerformed
88.236 + pythonPathModel.moveDown(pythonPath.getSelectedIndex());
88.237 +}//GEN-LAST:event_moveDownPythonPathActionPerformed
88.238 +
88.239 + private void manageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageActionPerformed
88.240 + //Workaround, Needs an API to display platform customizer
88.241 + final FileObject fo = FileUtil.getConfigFile("Actions/Python/org-netbeans-modules-python-platform-PythonManagerAction.instance"); //NOI18N
88.242 + if (fo != null) {
88.243 + try {
88.244 + InstanceDataObject ido = (InstanceDataObject) DataObject.find(fo);
88.245 + CallableSystemAction action = (CallableSystemAction) ido.instanceCreate();
88.246 + action.performAction();
88.247 + platforms.setModel(Utils.createPlatformModel()); //Currentl the PythonManager doesn't fire events, we need to replace model.
88.248 + } catch (IOException | ClassNotFoundException ex) {
88.249 + Exceptions.printStackTrace(ex);
88.250 + }
88.251 + }
88.252 +}//GEN-LAST:event_manageActionPerformed
88.253 +
88.254 + private void platformsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_platformsActionPerformed
88.255 + PythonPlatform selectedPlatform = (PythonPlatform) platforms.getSelectedItem();
88.256 + if (selectedPlatform != null) {
88.257 + project.setActivePlatform(selectedPlatform);
88.258 + }
88.259 + }//GEN-LAST:event_platformsActionPerformed
88.260 +
88.261 + // Variables declaration - do not modify//GEN-BEGIN:variables
88.262 + private javax.swing.JButton addPythonPath;
88.263 + private javax.swing.JLabel jLabel1;
88.264 + private javax.swing.JLabel jLabel2;
88.265 + private javax.swing.JScrollPane jScrollPane2;
88.266 + private javax.swing.JButton manage;
88.267 + private javax.swing.JButton moveDownPythonPath;
88.268 + private javax.swing.JButton moveUpPythonPath;
88.269 + private javax.swing.JComboBox platforms;
88.270 + private javax.swing.JList pythonPath;
88.271 + private javax.swing.JButton removePythonPath;
88.272 + // End of variables declaration//GEN-END:variables
88.273 +
88.274 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/CustomizerRun.form Tue Feb 24 01:58:36 2015 -0800
89.3 @@ -0,0 +1,113 @@
89.4 +<?xml version="1.0" encoding="UTF-8" ?>
89.5 +
89.6 +<Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
89.7 + <AuxValues>
89.8 + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
89.9 + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
89.10 + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
89.11 + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
89.12 + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
89.13 + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
89.14 + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
89.15 + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
89.16 + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
89.17 + </AuxValues>
89.18 +
89.19 + <Layout>
89.20 + <DimensionLayout dim="0">
89.21 + <Group type="103" groupAlignment="0" attributes="0">
89.22 + <Group type="102" attributes="0">
89.23 + <Group type="103" groupAlignment="0" attributes="0">
89.24 + <Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
89.25 + <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
89.26 + </Group>
89.27 + <EmptySpace max="-2" attributes="0"/>
89.28 + <Group type="103" groupAlignment="0" attributes="0">
89.29 + <Component id="mainModule" alignment="0" pref="364" max="32767" attributes="0"/>
89.30 + <Component id="appArgs" alignment="0" pref="364" max="32767" attributes="0"/>
89.31 + </Group>
89.32 + <EmptySpace type="unrelated" max="-2" attributes="0"/>
89.33 + <Component id="jButton1" min="-2" max="-2" attributes="0"/>
89.34 + <EmptySpace max="-2" attributes="0"/>
89.35 + </Group>
89.36 + </Group>
89.37 + </DimensionLayout>
89.38 + <DimensionLayout dim="1">
89.39 + <Group type="103" groupAlignment="0" attributes="0">
89.40 + <Group type="102" alignment="0" attributes="0">
89.41 + <Group type="103" groupAlignment="3" attributes="0">
89.42 + <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
89.43 + <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
89.44 + <Component id="mainModule" alignment="3" min="-2" max="-2" attributes="0"/>
89.45 + </Group>
89.46 + <EmptySpace max="-2" attributes="0"/>
89.47 + <Group type="103" groupAlignment="3" attributes="0">
89.48 + <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
89.49 + <Component id="appArgs" alignment="3" min="-2" max="-2" attributes="0"/>
89.50 + </Group>
89.51 + <EmptySpace pref="234" max="32767" attributes="0"/>
89.52 + </Group>
89.53 + </Group>
89.54 + </DimensionLayout>
89.55 + </Layout>
89.56 + <SubComponents>
89.57 + <Component class="javax.swing.JLabel" name="jLabel1">
89.58 + <Properties>
89.59 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
89.60 + <ComponentRef name="mainModule"/>
89.61 + </Property>
89.62 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.63 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerRun.mainModule.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.64 + </Property>
89.65 + </Properties>
89.66 + <AuxValues>
89.67 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
89.68 + </AuxValues>
89.69 + </Component>
89.70 + <Component class="javax.swing.JTextField" name="mainModule">
89.71 + <AccessibilityProperties>
89.72 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.73 + <ResourceString bundle="org/netbeans/modules/python/project/ui/customizer/Bundle.properties" key="CustomizerRun.mainModule.ad" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.74 + </Property>
89.75 + </AccessibilityProperties>
89.76 + </Component>
89.77 + <Component class="javax.swing.JButton" name="jButton1">
89.78 + <Properties>
89.79 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.80 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerRun.browseMain.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.81 + </Property>
89.82 + </Properties>
89.83 + <AccessibilityProperties>
89.84 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.85 + <ResourceString bundle="org/netbeans/modules/python/project/ui/customizer/Bundle.properties" key="CustomizerRun.browseMain.ad" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.86 + </Property>
89.87 + </AccessibilityProperties>
89.88 + <Events>
89.89 + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
89.90 + </Events>
89.91 + <AuxValues>
89.92 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
89.93 + </AuxValues>
89.94 + </Component>
89.95 + <Component class="javax.swing.JLabel" name="jLabel2">
89.96 + <Properties>
89.97 + <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
89.98 + <ComponentRef name="appArgs"/>
89.99 + </Property>
89.100 + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.101 + <ResourceString bundle="org/netbeans/modules/python/project2/ui/customizer/Bundle.properties" key="CustomizerRun.appArgs.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.102 + </Property>
89.103 + </Properties>
89.104 + <AuxValues>
89.105 + <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
89.106 + </AuxValues>
89.107 + </Component>
89.108 + <Component class="javax.swing.JTextField" name="appArgs">
89.109 + <AccessibilityProperties>
89.110 + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
89.111 + <ResourceString bundle="org/netbeans/modules/python/project/ui/customizer/Bundle.properties" key="CustomizerRun.appArgs.ad" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
89.112 + </Property>
89.113 + </AccessibilityProperties>
89.114 + </Component>
89.115 + </SubComponents>
89.116 +</Form>
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/CustomizerRun.java Tue Feb 24 01:58:36 2015 -0800
90.3 @@ -0,0 +1,152 @@
90.4 +/*
90.5 + * CustomizerRun.java
90.6 + *
90.7 + * Created on August 22, 2008, 4:52 PM
90.8 + */
90.9 +
90.10 +package org.netbeans.modules.python.project2.ui.customizer;
90.11 +
90.12 +import javax.swing.event.DocumentEvent;
90.13 +import javax.swing.event.DocumentListener;
90.14 +import javax.swing.text.Document;
90.15 +import org.netbeans.modules.python.project2.PythonProject2;
90.16 +import org.netbeans.modules.python.project2.ui.Utils;
90.17 +
90.18 +/**
90.19 + *
90.20 + * @author Tomas Zezula
90.21 + */
90.22 +public class CustomizerRun extends javax.swing.JPanel {
90.23 +
90.24 + private final PythonProject2 project;
90.25 + private final DocListener listener;
90.26 +
90.27 + /** Creates new form CustomizerRun */
90.28 + public CustomizerRun(final PythonProject2 project) {
90.29 + assert project != null;
90.30 + this.project = project;
90.31 + initComponents();
90.32 + String mainModule = project.getMainModule();
90.33 + if (mainModule != null) {
90.34 + this.mainModule.setText(mainModule);
90.35 + }
90.36 + String appArgs = project.getApplicationArgs();
90.37 + if (appArgs != null) {
90.38 + this.appArgs.setText(appArgs);
90.39 + }
90.40 + this.listener = new DocListener ();
90.41 + this.mainModule.getDocument().addDocumentListener(listener);
90.42 + this.appArgs.getDocument().addDocumentListener(listener);
90.43 + }
90.44 +
90.45 + /** This method is called from within the constructor to
90.46 + * initialize the form.
90.47 + * WARNING: Do NOT modify this code. The content of this method is
90.48 + * always regenerated by the Form Editor.
90.49 + */
90.50 + @SuppressWarnings("unchecked")
90.51 + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
90.52 + private void initComponents() {
90.53 +
90.54 + jLabel1 = new javax.swing.JLabel();
90.55 + mainModule = new javax.swing.JTextField();
90.56 + jButton1 = new javax.swing.JButton();
90.57 + jLabel2 = new javax.swing.JLabel();
90.58 + appArgs = new javax.swing.JTextField();
90.59 +
90.60 + jLabel1.setLabelFor(mainModule);
90.61 + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.mainModule.text")); // NOI18N
90.62 +
90.63 + org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.browseMain.text")); // NOI18N
90.64 + jButton1.addActionListener(new java.awt.event.ActionListener() {
90.65 + public void actionPerformed(java.awt.event.ActionEvent evt) {
90.66 + jButton1ActionPerformed(evt);
90.67 + }
90.68 + });
90.69 +
90.70 + jLabel2.setLabelFor(appArgs);
90.71 + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.appArgs.text")); // NOI18N
90.72 +
90.73 + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
90.74 + this.setLayout(layout);
90.75 + layout.setHorizontalGroup(
90.76 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
90.77 + .addGroup(layout.createSequentialGroup()
90.78 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
90.79 + .addComponent(jLabel2)
90.80 + .addComponent(jLabel1))
90.81 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
90.82 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
90.83 + .addComponent(mainModule, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE)
90.84 + .addComponent(appArgs, javax.swing.GroupLayout.DEFAULT_SIZE, 364, Short.MAX_VALUE))
90.85 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
90.86 + .addComponent(jButton1)
90.87 + .addContainerGap())
90.88 + );
90.89 + layout.setVerticalGroup(
90.90 + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
90.91 + .addGroup(layout.createSequentialGroup()
90.92 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
90.93 + .addComponent(jLabel1)
90.94 + .addComponent(jButton1)
90.95 + .addComponent(mainModule, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
90.96 + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
90.97 + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
90.98 + .addComponent(jLabel2)
90.99 + .addComponent(appArgs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
90.100 + .addContainerGap(234, Short.MAX_VALUE))
90.101 + );
90.102 +
90.103 + mainModule.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.mainModule.ad")); // NOI18N
90.104 + jButton1.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.browseMain.ad")); // NOI18N
90.105 + appArgs.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(CustomizerRun.class, "CustomizerRun.appArgs.ad")); // NOI18N
90.106 + }// </editor-fold>//GEN-END:initComponents
90.107 +
90.108 +private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
90.109 + String main = Utils.chooseMainModule(project);
90.110 + if (main != null) {
90.111 + mainModule.setText(main);
90.112 + }
90.113 +}//GEN-LAST:event_jButton1ActionPerformed
90.114 +
90.115 +
90.116 + // Variables declaration - do not modify//GEN-BEGIN:variables
90.117 + private javax.swing.JTextField appArgs;
90.118 + private javax.swing.JButton jButton1;
90.119 + private javax.swing.JLabel jLabel1;
90.120 + private javax.swing.JLabel jLabel2;
90.121 + private javax.swing.JTextField mainModule;
90.122 + // End of variables declaration//GEN-END:variables
90.123 +
90.124 +
90.125 + private class DocListener implements DocumentListener {
90.126 +
90.127 + @Override
90.128 + public void insertUpdate(DocumentEvent e) {
90.129 + handleDocEvent (e);
90.130 + }
90.131 +
90.132 + @Override
90.133 + public void removeUpdate(DocumentEvent e) {
90.134 + handleDocEvent(e);
90.135 + }
90.136 +
90.137 + @Override
90.138 + public void changedUpdate(DocumentEvent e) {
90.139 + handleDocEvent(e);
90.140 + }
90.141 +
90.142 + private void handleDocEvent (final DocumentEvent e) {
90.143 + final Document doc = e.getDocument();
90.144 + if (doc == mainModule.getDocument()) {
90.145 + //System.out.println("Updating main Module to " + mainModule.getText() );
90.146 +
90.147 + project.setMainModule(mainModule.getText());
90.148 + }
90.149 + else if (doc == appArgs.getDocument()) {
90.150 + project.setApplicationArgs(appArgs.getText());
90.151 + }
90.152 + }
90.153 +
90.154 + }
90.155 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/python.project2/src/org/netbeans/modules/python/project2/ui/customizer/PythonCustomizerProvider.java Tue Feb 24 01:58:36 2015 -0800
91.3 @@ -0,0 +1,118 @@
91.4 +/*
91.5 + * To change this template, choose Tools | Templates
91.6 + * and open the template in the editor.
91.7 + */
91.8 +package org.netbeans.modules.python.project2.ui.customizer;
91.9 +
91.10 +import java.awt.Dialog;
91.11 +import java.awt.event.ActionEvent;
91.12 +import java.awt.event.ActionListener;
91.13 +import java.awt.event.WindowAdapter;
91.14 +import java.awt.event.WindowEvent;
91.15 +import java.text.MessageFormat;
91.16 +import java.util.HashMap;
91.17 +import java.util.Map;
91.18 +import org.netbeans.modules.python.project2.PythonProject2;
91.19 +import org.netbeans.api.project.Project;
91.20 +import org.netbeans.api.project.ProjectUtils;
91.21 +import org.netbeans.spi.project.ui.CustomizerProvider;
91.22 +import org.netbeans.spi.project.ui.support.ProjectCustomizer;
91.23 +import org.openide.util.Lookup;
91.24 +import org.openide.util.NbBundle;
91.25 +import org.openide.util.lookup.Lookups;
91.26 +
91.27 +/**
91.28 + *
91.29 + * @author Tomas Zezula
91.30 + */
91.31 +public class PythonCustomizerProvider implements CustomizerProvider {
91.32 +
91.33 + private static final String CUSTOMIZER_FOLDER_PATH = "Projects/org-netbeans-modules-python-project2//Customizer"; //NO18N
91.34 +
91.35 + private static final Map<Project, Dialog> PROJECT_2_DIALOG = new HashMap<>();
91.36 +
91.37 + private final PythonProject2 project;
91.38 +
91.39 + public PythonCustomizerProvider(final PythonProject2 project) {
91.40 + assert project != null;
91.41 + this.project = project;
91.42 + }
91.43 +
91.44 + @Override
91.45 + public void showCustomizer() {
91.46 + showCustomizer(null);
91.47 + }
91.48 +
91.49 + public void showCustomizer(String preselectedCategory) {
91.50 + Dialog dialog = PROJECT_2_DIALOG.get(project);
91.51 + if (dialog != null) {
91.52 + dialog.setVisible(true);
91.53 + return;
91.54 + }
91.55 +
91.56 + final Lookup context = Lookups.fixed(project);
91.57 + final OptionListener optionListener = new OptionListener(project);
91.58 + final StoreListener storeListener = new StoreListener(project);
91.59 + dialog = ProjectCustomizer.createCustomizerDialog(CUSTOMIZER_FOLDER_PATH, context, preselectedCategory,
91.60 + optionListener, storeListener, null);
91.61 + dialog.addWindowListener(optionListener);
91.62 + dialog.setTitle(MessageFormat.format(
91.63 + NbBundle.getMessage(PythonCustomizerProvider.class, "LBL_Customizer_Title"),
91.64 + ProjectUtils.getInformation(project).getDisplayName()));
91.65 +
91.66 + PROJECT_2_DIALOG.put(project, dialog);
91.67 + dialog.setVisible(true);
91.68 + }
91.69 +
91.70 + private class StoreListener implements ActionListener {
91.71 +
91.72 + private final PythonProject2 uiProperties;
91.73 +
91.74 + StoreListener(PythonProject2 uiProperties) {
91.75 + this.uiProperties = uiProperties;
91.76 + }
91.77 +
91.78 + @Override
91.79 + public void actionPerformed(ActionEvent e) {
91.80 +// uiProperties.save();
91.81 + }
91.82 + }
91.83 +
91.84 + private static class OptionListener extends WindowAdapter implements ActionListener {
91.85 +
91.86 + private final Project project;
91.87 +
91.88 + OptionListener(Project project) {
91.89 + this.project = project;
91.90 + }
91.91 +
91.92 + // Listening to OK button ----------------------------------------------
91.93 + @Override
91.94 + public void actionPerformed(ActionEvent e) {
91.95 + // Close & dispose the the dialog
91.96 + Dialog dialog = PROJECT_2_DIALOG.get(project);
91.97 + if (dialog != null) {
91.98 + dialog.setVisible(false);
91.99 + dialog.dispose();
91.100 + }
91.101 + }
91.102 +
91.103 + // Listening to window events ------------------------------------------
91.104 + @Override
91.105 + public void windowClosed(WindowEvent e) {
91.106 + PROJECT_2_DIALOG.remove(project);
91.107 + }
91.108 +
91.109 + @Override
91.110 + public void windowClosing(WindowEvent e) {
91.111 + //Dispose the dialog otherwsie the {@link WindowAdapter#windowClosed}
91.112 + //may not be called
91.113 + Dialog dialog = PROJECT_2_DIALOG.get(project);
91.114 + if (dialog != null) {
91.115 + dialog.setVisible(false);
91.116 + dialog.dispose();
91.117 + }
91.118 + }
91.119 + }
91.120 +
91.121 +}
92.1 --- a/python.source/nbproject/project.xml Wed Feb 04 01:21:44 2015 -0800
92.2 +++ b/python.source/nbproject/project.xml Tue Feb 24 01:58:36 2015 -0800
92.3 @@ -16,6 +16,15 @@
92.4 </run-dependency>
92.5 </dependency>
92.6 <dependency>
92.7 + <code-name-base>org.netbeans.modules.projectapi</code-name-base>
92.8 + <build-prerequisite/>
92.9 + <compile-dependency/>
92.10 + <run-dependency>
92.11 + <release-version>1</release-version>
92.12 + <specification-version>1.60.2</specification-version>
92.13 + </run-dependency>
92.14 + </dependency>
92.15 + <dependency>
92.16 <code-name-base>org.openide.filesystems</code-name-base>
92.17 <build-prerequisite/>
92.18 <compile-dependency/>
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/python.source/src/org/netbeans/modules/python/source/PythonProjectSourceLevelQuery.java Tue Feb 24 01:58:36 2015 -0800
93.3 @@ -0,0 +1,29 @@
93.4 +/*
93.5 + * To change this license header, choose License Headers in Project Properties.
93.6 + * To change this template file, choose Tools | Templates
93.7 + * and open the template in the editor.
93.8 + */
93.9 +package org.netbeans.modules.python.source;
93.10 +
93.11 +import org.netbeans.modules.python.source.queries.SourceLevelQueryImplementation;
93.12 +import org.netbeans.api.project.FileOwnerQuery;
93.13 +import org.netbeans.api.project.Project;
93.14 +import org.openide.filesystems.FileObject;
93.15 +import org.openide.util.lookup.ServiceProvider;
93.16 +
93.17 +@ServiceProvider(service = SourceLevelQueryImplementation.class, position = 400)
93.18 +public class PythonProjectSourceLevelQuery implements SourceLevelQueryImplementation {
93.19 +
93.20 + @Override
93.21 + public Result getSourceLevel(FileObject pythonFile) {
93.22 + final Project project = FileOwnerQuery.getOwner(pythonFile);
93.23 + if (project != null) {
93.24 + SourceLevelQueryImplementation impl = project.getLookup().lookup(SourceLevelQueryImplementation.class);
93.25 + if (impl != null) {
93.26 + return impl.getSourceLevel(pythonFile);
93.27 + }
93.28 + }
93.29 + return null;
93.30 + }
93.31 +
93.32 +}