001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * RemoteFilesystemChooser.java
044: *
045: * Created on February 26, 2007, 4:31 PM
046: *
047: * To change this template, choose Tools | Template Manager
048: * and open the template in the editor.
049: */
050:
051: package org.netbeans.modules.j2me.cdc.project.nsicom;
052:
053: import java.awt.BorderLayout;
054: import java.awt.Color;
055: import java.awt.Dimension;
056: import java.awt.Image;
057: import java.beans.BeanInfo;
058: import java.beans.PropertyChangeEvent;
059: import java.beans.PropertyChangeListener;
060: import java.util.Arrays;
061: import java.util.Collections;
062: import java.util.Comparator;
063: import javax.swing.ImageIcon;
064: import javax.swing.JLabel;
065: import javax.swing.JPanel;
066: import javax.swing.SwingUtilities;
067: import javax.swing.UIManager;
068: import javax.swing.border.LineBorder;
069: import org.netbeans.mobility.activesync.ActiveSyncException;
070: import org.netbeans.mobility.activesync.ActiveSyncOps;
071: import org.netbeans.mobility.activesync.DeviceConnectedListener;
072: import org.netbeans.mobility.activesync.RemoteFile; //todo import org.netbeans.modules.java.ui.nodes.SourceNodes;
073: import org.openide.NotifyDescriptor;
074: import org.openide.explorer.ExplorerManager;
075: import org.openide.explorer.view.BeanTreeView;
076: import org.openide.nodes.AbstractNode;
077: import org.openide.nodes.Children;
078: import org.openide.nodes.Node;
079: import org.openide.nodes.NodeOp;
080: import org.openide.util.NbBundle;
081: import org.openide.util.RequestProcessor;
082: import org.openide.util.Utilities;
083: import org.openide.util.lookup.Lookups;
084:
085: /**
086: *
087: * @author suchys
088: */
089: final class RemoteFilesystemChooser extends JPanel implements
090: ExplorerManager.Provider {
091:
092: private static String currentFolder;
093: private String selectedFolder;
094:
095: private static boolean foldersOnly;
096: private ExplorerManager em;
097: private static final ImageIcon CDC_PROJECT_ICON = new ImageIcon(
098: Utilities
099: .loadImage("org/netbeans/modules/j2me/cdc/project/resources/cdcProject.png")); // NOI18N
100: private static final String FOLDER_ICON_BASE = "org/openide/loaders/defaultFolder"; //NOI18N
101:
102: private PropertyChangeListener pcl = new PropertyChangeListener() {
103: public void propertyChange(PropertyChangeEvent evt) {
104: if (ExplorerManager.PROP_SELECTED_NODES.equals(evt
105: .getPropertyName())) {
106: if (getExplorerManager().getSelectedNodes().length == 1) {
107: RemoteFile remote = (RemoteFile) getExplorerManager()
108: .getSelectedNodes()[0].getLookup().lookup(
109: RemoteFile.class);
110: if (remote == null) {
111: RemoteFilesystemChooser.this
112: .firePropertyChange(
113: NotifyDescriptor.PROP_VALID,
114: true, false);
115: return;
116: }
117: if (foldersOnly && !remote.isDirectory()) {
118: RemoteFilesystemChooser.this
119: .firePropertyChange(
120: NotifyDescriptor.PROP_VALID,
121: true, false);
122: return;
123: } else if (!foldersOnly && remote.isDirectory()) {
124: RemoteFilesystemChooser.this
125: .firePropertyChange(
126: NotifyDescriptor.PROP_VALID,
127: true, false);
128: return;
129: }
130: String[] path = NodeOp.createPath(
131: getExplorerManager().getSelectedNodes()[0],
132: getExplorerManager().getRootContext());
133: StringBuffer sb = new StringBuffer("\\"); //NOI18N
134: for (int i = 0; i < path.length; i++) {
135: sb.append(path[i]);
136: if (i + 1 < path.length) {
137: sb.append("\\"); //NOI18N
138: }
139: }
140: selectedFolder = sb.toString();
141: RemoteFilesystemChooser.this .firePropertyChange(
142: NotifyDescriptor.PROP_VALID, false, true);
143: } else {
144: RemoteFilesystemChooser.this .firePropertyChange(
145: NotifyDescriptor.PROP_VALID, true, false);
146: }
147: }
148: }
149: };
150:
151: private ConnectionListener connectionListener;
152:
153: /** Creates a new instance of RemoteFilesystemChooser */
154: public RemoteFilesystemChooser(String curentFolder,
155: final boolean foldersOnly) {
156: this .currentFolder = currentFolder;
157: this .foldersOnly = foldersOnly;
158: this .selectedFolder = curentFolder;
159: this .setPreferredSize(new Dimension(400, 500));
160: setLayout(new BorderLayout());
161: try {
162: if (ActiveSyncOps.isAvailable()) {
163: if (!ActiveSyncOps.getDefault().isDeviceConnected()) {
164: createView(NbBundle.getMessage(
165: RemoteFilesystemChooser.class,
166: "ERROR_DeviceDisconnected")); //NOI18N
167: } else {
168: createView(null);
169: }
170: } else {
171: createView(NbBundle.getMessage(
172: RemoteFilesystemChooser.class,
173: "ERROR_ActiveSyntNotInstalled")); //NOI18N
174: }
175: } catch (ActiveSyncException ex) {
176: createView(NbBundle.getMessage(
177: RemoteFilesystemChooser.class,
178: "ERROR_ActiveSyncGeneralError")); //NOI18N
179: }
180: }
181:
182: public ExplorerManager getExplorerManager() {
183: if (em == null) {
184: em = new ExplorerManager();
185: }
186: return em;
187: }
188:
189: public String getSelectedFile() {
190: return selectedFolder;
191: }
192:
193: public void addNotify() {
194: super .addNotify();
195: try {
196: ActiveSyncOps.getDefault().addConnectionListener(
197: connectionListener = new ConnectionListener());
198: } catch (ActiveSyncException ex) {
199: }
200:
201: }
202:
203: public void removeNotify() {
204: try {
205: ActiveSyncOps.getDefault().removeConnectionListener(
206: connectionListener);
207: } catch (ActiveSyncException ex) {
208: }
209: super .removeNotify();
210: }
211:
212: private void createView(final String message) {
213: if (SwingUtilities.isEventDispatchThread()) {
214: if (message == null) {
215: createFileView();
216: } else {
217: createErrorView(message);
218: }
219: } else {
220: SwingUtilities.invokeLater(new Runnable() {
221: public void run() {
222: createView(message);
223: }
224: });
225: }
226: }
227:
228: private void createFileView() {
229: setVisible(false);
230: removeAll();
231: //check the availability if active sync here, if not, put some warning panel here
232: BeanTreeView btw = new BeanTreeView();
233: btw.setBorder(new LineBorder(Color.BLACK, 1, true));
234: add(btw, BorderLayout.CENTER);
235: try {
236: getExplorerManager().setRootContext(
237: new AbstractNode(new RemoteFileSystemChildren(
238: ActiveSyncOps.getDefault()
239: .getRootFilesystems()[0])) {
240: public String getName() {
241: return "\\"; //NOI18N
242: }
243:
244: public Image getIcon(int type) {
245: return CDC_PROJECT_ICON.getImage();
246: }
247:
248: public Image getOpenedIcon(int i) {
249: return getIcon(i);
250: }
251: });
252: } catch (ActiveSyncException ex) {
253: createView(NbBundle.getMessage(
254: RemoteFilesystemChooser.class,
255: "ERROR_ActiveSyncGeneralError")); //NOI18N
256: }
257: //how to with lazy inicialization?
258: // try {
259: // Node path = NodeOp.findPath(getExplorerManager().getRootContext(), new StringTokenizer(curentFolder, "/\\")); //NOI18N
260: // getExplorerManager().setSelectedNodes(new Node[]{path});
261: // } catch (NodeNotFoundException ex) {
262: // ex.printStackTrace();
263: // } catch (PropertyVetoException ex) {
264: // ex.printStackTrace();
265: // }
266: getExplorerManager().addPropertyChangeListener(pcl);
267: invalidate();
268: setVisible(true);
269: }
270:
271: private void createErrorView(String error) {
272: setVisible(false);
273: removeAll();
274: getExplorerManager().removePropertyChangeListener(pcl);
275: try {
276: getExplorerManager().setRootContext(
277: new AbstractNode(Children.LEAF)); //??
278: } catch (Exception e) {
279: e.printStackTrace();
280: }
281: ;
282: RemoteFilesystemChooser.this .firePropertyChange(
283: NotifyDescriptor.PROP_VALID, true, false);
284: JLabel errorLabel = new JLabel(error);
285: add(errorLabel, BorderLayout.CENTER);
286: invalidate();
287: setVisible(true);
288:
289: }
290:
291: private static class RemoteFileSystemNode extends AbstractNode {
292: private RemoteFile file;
293:
294: RemoteFileSystemNode(RemoteFile file, Children children) {
295: super (children, Lookups.singleton(file));
296: this .file = file;
297: setIconBase(FOLDER_ICON_BASE);
298: }
299:
300: public String getName() {
301: return file.getName();
302: }
303:
304: /** Overrides folder icon to search for icon in UIManager table for
305: * BeanInfo.ICON_COLOR_16x16 type, to allow for different icons
306: * across Look and Feels.
307: * Keeps possibility of icon annotations.
308: */
309: public Image getIcon(int type) {
310: Image img = null;
311: if (type == BeanInfo.ICON_COLOR_16x16) {
312: // search for proper folder icon installed by core/windows module
313: img = (Image) UIManager.get("Nb.Explorer.Folder.icon"); //NOI18N
314: }
315: if (img == null) {
316: img = super .getIcon(type);
317: }
318: return img;
319: }
320:
321: /** Overrides folder icon to search for icon in UIManager table for
322: * BeanInfo.ICON_COLOR_16x16 type, to allow for different icons
323: * across Look and Feels.
324: * Keeps possibility of icon annotations.
325: */
326: public Image getOpenedIcon(int type) {
327: Image img = null;
328: if (type == BeanInfo.ICON_COLOR_16x16) {
329: // search for proper folder icon installed by core/windows module
330: img = (Image) UIManager
331: .get("Nb.Explorer.Folder.openedIcon");
332: }
333: if (img == null) {
334: img = super .getOpenedIcon(type);
335: }
336: return img;
337: }
338: }
339:
340: private static class RemoteFileSystemChildren extends Children.Keys {
341: private RemoteFile folder;
342:
343: RemoteFileSystemChildren(RemoteFile folder) {
344: this .folder = folder;
345: }
346:
347: protected Node[] createNodes(Object object) {
348: if (object instanceof RemoteFile) {
349: try {
350: RemoteFile file = (RemoteFile) object;
351: if (foldersOnly) {
352: if (!file.isDirectory()) {
353: return new AbstractNode[] {};
354: }
355: }
356: return new AbstractNode[] { file.isDirectory() ? new RemoteFileSystemNode(
357: file, new RemoteFileSystemChildren(file))
358: : new RemoteFileSystemNode(file,
359: Children.LEAF) };
360: } catch (Exception ex) {
361: return new AbstractNode[] {}; //error here
362: }
363: } else {
364: Node waitNode = new AbstractNode(Children.LEAF);//todo SourceNodes.getExplorerFactory().createWaitNode();
365: waitNode.setName(NbBundle.getMessage(
366: RemoteFilesystemChooser.class, "NodeWait")); //NOI18N
367: return new Node[] { waitNode };
368: }
369: }
370:
371: protected void addNotify() {
372: super .addNotify();
373: setKeys(new Object[] { new Object() }); //do a static object
374: RequestProcessor.getDefault().post(new Runnable() {
375: public void run() {
376: try {
377: ActiveSyncOps activeSync = ActiveSyncOps
378: .getDefault();
379: RemoteFile[] files = activeSync
380: .listFiles(folder);
381: //sort here by folders first, then by names
382: Arrays.sort(files, REMOTE_FILE_COMPARATOR);
383: setKeys(files);
384: } catch (ActiveSyncException ex) {
385: }
386: }
387: });
388: }
389:
390: protected void removeNotify() {
391: super .removeNotify();
392: setKeys(Collections.EMPTY_LIST);
393: }
394: }
395:
396: private static Comparator REMOTE_FILE_COMPARATOR = new Comparator() {
397: public int compare(Object o1, Object o2) {
398: RemoteFile rf1 = (RemoteFile) o1;
399: RemoteFile rf2 = (RemoteFile) o2;
400: if ((rf1.isDirectory() && rf2.isDirectory())
401: || (!rf1.isDirectory() && !rf2.isDirectory())) {
402: return rf1.getName().compareTo(rf2.getName());
403: } else {
404: return !rf1.isDirectory() && rf2.isDirectory() ? 1 : -1;
405: }
406: }
407: };
408:
409: private class ConnectionListener implements DeviceConnectedListener {
410: public void onDeviceConnected(boolean connected) {
411: if (connected) {
412: createView(null);
413: } else {
414: createView(NbBundle.getMessage(
415: RemoteFilesystemChooser.class,
416: "ERROR_DeviceDisconnected")); //NOI18N
417: RemoteFilesystemChooser.this .firePropertyChange(
418: NotifyDescriptor.PROP_VALID, true, false);
419: }
420: }
421: }
422: }
|