|
|
@ -1,5 +1,18 @@ |
|
|
|
package com.fr.design.gui.itree.filetree; |
|
|
|
package com.fr.design.gui.itree.filetree; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.fr.base.BaseUtils; |
|
|
|
|
|
|
|
import com.fr.design.i18n.Toolkit; |
|
|
|
|
|
|
|
import com.fr.general.ComparatorUtils; |
|
|
|
|
|
|
|
import com.fr.stable.ArrayUtils; |
|
|
|
|
|
|
|
import com.fr.stable.project.ProjectConstants; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import javax.swing.Icon; |
|
|
|
|
|
|
|
import javax.swing.JTree; |
|
|
|
|
|
|
|
import javax.swing.filechooser.FileSystemView; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultMutableTreeNode; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultTreeCellRenderer; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultTreeModel; |
|
|
|
|
|
|
|
import javax.swing.tree.TreePath; |
|
|
|
import java.awt.Color; |
|
|
|
import java.awt.Color; |
|
|
|
import java.awt.Component; |
|
|
|
import java.awt.Component; |
|
|
|
import java.awt.Font; |
|
|
|
import java.awt.Font; |
|
|
@ -11,26 +24,12 @@ import java.util.Comparator; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Stack; |
|
|
|
import java.util.Stack; |
|
|
|
|
|
|
|
|
|
|
|
import javax.swing.Icon; |
|
|
|
|
|
|
|
import javax.swing.JTree; |
|
|
|
|
|
|
|
import javax.swing.filechooser.FileSystemView; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultMutableTreeNode; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultTreeCellRenderer; |
|
|
|
|
|
|
|
import javax.swing.tree.DefaultTreeModel; |
|
|
|
|
|
|
|
import javax.swing.tree.TreePath; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.fr.base.BaseUtils; |
|
|
|
|
|
|
|
import com.fr.general.ComparatorUtils; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.fr.stable.ArrayUtils; |
|
|
|
|
|
|
|
import com.fr.stable.project.ProjectConstants; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* File Tree. |
|
|
|
* File Tree. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class JFileTree extends AbstractFileTree { |
|
|
|
public class JFileTree extends AbstractFileTree { |
|
|
|
protected FileFilter fileFilter ; |
|
|
|
protected FileFilter fileFilter; |
|
|
|
|
|
|
|
|
|
|
|
public JFileTree() { |
|
|
|
public JFileTree() { |
|
|
|
this(null); |
|
|
|
this(null); |
|
|
@ -43,9 +42,9 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
private void init(FileFilter filter) { |
|
|
|
private void init(FileFilter filter) { |
|
|
|
this.fileFilter = filter; |
|
|
|
this.fileFilter = filter; |
|
|
|
|
|
|
|
|
|
|
|
DefaultTreeModel m_model = new DefaultTreeModel(new DefaultMutableTreeNode(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_My_Computer"))); |
|
|
|
DefaultTreeModel treeModel = new DefaultTreeModel(new DefaultMutableTreeNode(Toolkit.i18nText("Fine-Design_Basic_My_Computer"))); |
|
|
|
this.setModel(m_model); |
|
|
|
this.setModel(treeModel); |
|
|
|
|
|
|
|
|
|
|
|
this.putClientProperty("JTree.lineStyle", "Angled"); |
|
|
|
this.putClientProperty("JTree.lineStyle", "Angled"); |
|
|
|
|
|
|
|
|
|
|
|
this.addTreeExpansionListener(this); |
|
|
|
this.addTreeExpansionListener(this); |
|
|
@ -57,7 +56,7 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setRootFile(File rootFile) { |
|
|
|
public void setRootFile(File rootFile) { |
|
|
|
setRootFiles(new File[] { rootFile }); |
|
|
|
setRootFiles(new File[]{rootFile}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setRootFiles(File[] rootFiles) { |
|
|
|
public void setRootFiles(File[] rootFiles) { |
|
|
@ -65,8 +64,8 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DefaultTreeModel m_model = (DefaultTreeModel) this.getModel(); |
|
|
|
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.getModel(); |
|
|
|
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) m_model.getRoot(); |
|
|
|
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); |
|
|
|
rootTreeNode.removeAllChildren(); |
|
|
|
rootTreeNode.removeAllChildren(); |
|
|
|
|
|
|
|
|
|
|
|
for (int k = 0; k < rootFiles.length; k++) { |
|
|
|
for (int k = 0; k < rootFiles.length; k++) { |
|
|
@ -78,7 +77,7 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// richer:不是LocalEnv根本就不会运行到这儿
|
|
|
|
// richer:不是LocalEnv根本就不会运行到这儿
|
|
|
|
m_model.reload(rootTreeNode); |
|
|
|
defaultTreeModel.reload(rootTreeNode); |
|
|
|
|
|
|
|
|
|
|
|
if (rootFiles.length == 1) { |
|
|
|
if (rootFiles.length == 1) { |
|
|
|
File expandFile = rootFiles[0]; |
|
|
|
File expandFile = rootFiles[0]; |
|
|
@ -96,22 +95,19 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
|
|
|
|
|
|
|
|
public File getSelectedFile() { |
|
|
|
public File getSelectedFile() { |
|
|
|
TreePath selectedTreePath = this.getSelectionPath(); |
|
|
|
TreePath selectedTreePath = this.getSelectionPath(); |
|
|
|
if(selectedTreePath == null) { |
|
|
|
if (selectedTreePath == null) { |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DefaultMutableTreeNode currentTreeNode = this.getMutableTreeNode(selectedTreePath); |
|
|
|
DefaultMutableTreeNode currentTreeNode = this.getMutableTreeNode(selectedTreePath); |
|
|
|
StringBuffer fBuf = new StringBuffer(); |
|
|
|
StringBuilder fBuf = new StringBuilder(); |
|
|
|
while (true) { |
|
|
|
while (currentTreeNode != null) { |
|
|
|
// 如果已经到了根节点,直接退出.
|
|
|
|
// 如果已经到了根节点,直接退出.
|
|
|
|
if (currentTreeNode == null) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object object = currentTreeNode.getUserObject(); |
|
|
|
Object object = currentTreeNode.getUserObject(); |
|
|
|
if (object instanceof RootFile) { |
|
|
|
if (object instanceof RootFile) { |
|
|
|
// 当前文件.
|
|
|
|
// 当前文件.
|
|
|
|
RootFile rootFileNode = (RootFile) object; |
|
|
|
RootFile rootFileNode = (RootFile) object; |
|
|
|
return new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
return new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -128,6 +124,7 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 通过文件夹寻找展开路径 |
|
|
|
* 通过文件夹寻找展开路径 |
|
|
|
|
|
|
|
* |
|
|
|
* @param currentFile 当前文件 |
|
|
|
* @param currentFile 当前文件 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void selectFile(File currentFile) { |
|
|
|
public void selectFile(File currentFile) { |
|
|
@ -181,26 +178,25 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 列出当前所有的File |
|
|
|
* 列出当前所有的File |
|
|
|
|
|
|
|
* |
|
|
|
* @param currentTreeNode 当前文件节点 |
|
|
|
* @param currentTreeNode 当前文件节点 |
|
|
|
* @return 当前节点下的所有File |
|
|
|
* @return 当前节点下的所有File |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
@Override |
|
|
|
public FileDirectoryNode[] listFileNodes(DefaultMutableTreeNode currentTreeNode) { |
|
|
|
public FileDirectoryNode[] listFileNodes(DefaultMutableTreeNode currentTreeNode) { |
|
|
|
StringBuffer fBuf = new StringBuffer(); |
|
|
|
StringBuilder fBuf = new StringBuilder(); |
|
|
|
while (true) { |
|
|
|
while (currentTreeNode != null) { |
|
|
|
// 如果已经到了根节点,直接退出.
|
|
|
|
// 如果已经到了根节点,直接退出.
|
|
|
|
if (currentTreeNode == null) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Object object = currentTreeNode.getUserObject(); |
|
|
|
Object object = currentTreeNode.getUserObject(); |
|
|
|
if (object instanceof RootFile) { |
|
|
|
if (object instanceof RootFile) { |
|
|
|
RootFile rootFileNode = (RootFile) object; |
|
|
|
RootFile rootFileNode = (RootFile) object; |
|
|
|
// 当前文件. (rootFileNode + fBuf.toString = Path local地址)
|
|
|
|
// 当前文件. (rootFileNode + fBuf.toString = Path local地址)
|
|
|
|
File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
// 列出当前文件的所有子文件,要判断下是否是系统保护的文件 能否打开. 打不开的话显示为null
|
|
|
|
// 列出当前文件的所有子文件,要判断下是否是系统保护的文件 能否打开. 打不开的话显示为null
|
|
|
|
File[] files = currentFile.listFiles(); |
|
|
|
File[] files = currentFile.listFiles(); |
|
|
|
// 如果文件列表为null 或者为File[0] = []返回null
|
|
|
|
// 如果文件列表为null 或者为File[0] = []返回null
|
|
|
|
if (files == null ) { |
|
|
|
if (files == null) { |
|
|
|
return new FileDirectoryNode[0]; |
|
|
|
return new FileDirectoryNode[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
List fileNodeList = new ArrayList(); |
|
|
|
List fileNodeList = new ArrayList(); |
|
|
|
for (int k = 0; k < files.length; k++) { |
|
|
|
for (int k = 0; k < files.length; k++) { |
|
|
@ -211,8 +207,8 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
} |
|
|
|
} |
|
|
|
// 过滤只显示文件夹 并进行 名字简化
|
|
|
|
// 过滤只显示文件夹 并进行 名字简化
|
|
|
|
if (fileFilter.accept(tmpFile)) { |
|
|
|
if (fileFilter.accept(tmpFile)) { |
|
|
|
// newNode 传递 isDirectory属性 并且只显示文件夹名字
|
|
|
|
// newNode 传递 isDirectory属性 并且只显示文件夹名字
|
|
|
|
FileDirectoryNode newNode = FileDirectoryNode.createFileDirectoryNode(tmpFile); |
|
|
|
FileDirectoryNode newNode = FileDirectoryNode.createFileDirectoryNode(tmpFile); |
|
|
|
fileNodeList.add(newNode); |
|
|
|
fileNodeList.add(newNode); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -220,78 +216,77 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
FileDirectoryNode[] fileNodes = new FileDirectoryNode[fileNodeList.size()]; |
|
|
|
FileDirectoryNode[] fileNodes = new FileDirectoryNode[fileNodeList.size()]; |
|
|
|
fileNodeList.toArray(fileNodes); |
|
|
|
fileNodeList.toArray(fileNodes); |
|
|
|
// 对文件夹进行排序
|
|
|
|
// 对文件夹进行排序
|
|
|
|
Arrays.sort(fileNodes, new FileNodeComparator()); |
|
|
|
Arrays.sort(fileNodes, new FileDirectoryNodeComparator()); |
|
|
|
return fileNodes; |
|
|
|
return fileNodes; |
|
|
|
} |
|
|
|
} |
|
|
|
// 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload ,返回到文件夹的path,因为有可能是String. 所以加上instanceof
|
|
|
|
// 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload ,返回到文件夹的path,因为有可能是String. 所以加上instanceof
|
|
|
|
if (object instanceof FileDirectoryNode) { |
|
|
|
if (object instanceof FileDirectoryNode) { |
|
|
|
FileDirectoryNode nameNode = (FileDirectoryNode)object; |
|
|
|
FileDirectoryNode nameNode = (FileDirectoryNode) object; |
|
|
|
fBuf.insert(0, nameNode.getName()); |
|
|
|
fBuf.insert(0, nameNode.getName()); |
|
|
|
fBuf.insert(0, "/"); |
|
|
|
fBuf.insert(0, "/"); |
|
|
|
} |
|
|
|
} |
|
|
|
// 逐层返回
|
|
|
|
// 逐层返回
|
|
|
|
currentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); |
|
|
|
currentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); |
|
|
|
} |
|
|
|
} |
|
|
|
return new FileDirectoryNode[0]; |
|
|
|
return new FileDirectoryNode[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* cellRenderer: tree中显示文件的类型图标 |
|
|
|
* cellRenderer: tree中显示文件的类型图标 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() { |
|
|
|
private DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() { |
|
|
|
|
|
|
|
|
|
|
|
public Component getTreeCellRendererComponent(JTree tree, Object value, |
|
|
|
@Override |
|
|
|
boolean selected, boolean expanded, boolean leaf, int row, |
|
|
|
public Component getTreeCellRendererComponent(JTree tree, Object value, |
|
|
|
boolean hasFocus) { |
|
|
|
boolean selected, boolean expanded, boolean leaf, int row, |
|
|
|
super.getTreeCellRendererComponent(tree, value, selected, expanded, |
|
|
|
boolean hasFocus) { |
|
|
|
leaf, row, hasFocus); |
|
|
|
super.getTreeCellRendererComponent(tree, value, selected, expanded, |
|
|
|
|
|
|
|
leaf, row, hasFocus); |
|
|
|
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; |
|
|
|
|
|
|
|
StringBuffer fBuf = new StringBuffer(); |
|
|
|
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; |
|
|
|
while(true) { |
|
|
|
StringBuilder fBuf = new StringBuilder(); |
|
|
|
if (treeNode == null) { |
|
|
|
while (treeNode != null) { |
|
|
|
break; |
|
|
|
Object userObj = treeNode.getUserObject(); |
|
|
|
} |
|
|
|
if (userObj instanceof RootFile) { |
|
|
|
Object userObj = treeNode.getUserObject(); |
|
|
|
RootFile rootFileNode = (RootFile) userObj; |
|
|
|
if (userObj instanceof RootFile) { |
|
|
|
// 当前文件的全部路径. (rootFileNode + fBuf.toString = Path local地址)
|
|
|
|
RootFile rootFileNode = (RootFile) userObj; |
|
|
|
File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
// 当前文件的全部路径. (rootFileNode + fBuf.toString = Path local地址)
|
|
|
|
FileSystemView view = FileSystemView.getFileSystemView(); |
|
|
|
File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); |
|
|
|
// File的全部路径.
|
|
|
|
FileSystemView view = FileSystemView.getFileSystemView(); |
|
|
|
// 得到本地tree图标
|
|
|
|
// File的全部路径.
|
|
|
|
Icon tmpIcon = view.getSystemIcon(currentFile); |
|
|
|
// 得到本地tree图标
|
|
|
|
|
|
|
|
Icon tmpIcon = view.getSystemIcon(currentFile); |
|
|
|
|
|
|
|
if (currentFile.isDirectory() && fBuf.length() > 0) { |
|
|
|
if (currentFile.isDirectory() && fBuf.length() > 0) { |
|
|
|
tmpIcon=BaseUtils.readIcon("/com/fr/design/images/gui/folder.png"); |
|
|
|
tmpIcon = BaseUtils.readIcon("/com/fr/design/images/gui/folder.png"); |
|
|
|
} |
|
|
|
} |
|
|
|
this.setIcon(tmpIcon); |
|
|
|
this.setIcon(tmpIcon); |
|
|
|
this.setName(null); |
|
|
|
this.setName(null); |
|
|
|
Font oldFont = this.getFont(); |
|
|
|
Font oldFont = this.getFont(); |
|
|
|
if(ComparatorUtils.equals(currentFile.getName(), ProjectConstants.WEBINF_NAME)){ |
|
|
|
if (ComparatorUtils.equals(currentFile.getName(), ProjectConstants.WEBINF_NAME)) { |
|
|
|
this.setForeground(Color.blue); |
|
|
|
this.setForeground(Color.blue); |
|
|
|
this.setFont(new Font(oldFont.getName(),1,oldFont.getSize())); |
|
|
|
this.setFont(new Font(oldFont.getName(), Font.BOLD, oldFont.getSize())); |
|
|
|
}else{ |
|
|
|
} else { |
|
|
|
this.setFont(new Font(oldFont.getName(),0,oldFont.getSize())); |
|
|
|
this.setFont(new Font(oldFont.getName(), Font.PLAIN, oldFont.getSize())); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload
|
|
|
|
// 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload
|
|
|
|
if (userObj instanceof FileDirectoryNode ) { |
|
|
|
if (userObj instanceof FileDirectoryNode) { |
|
|
|
FileDirectoryNode nameNode = (FileDirectoryNode)userObj; |
|
|
|
FileDirectoryNode nameNode = (FileDirectoryNode) userObj; |
|
|
|
fBuf.insert(0, nameNode.getName()); |
|
|
|
fBuf.insert(0, nameNode.getName()); |
|
|
|
fBuf.insert(0, "/"); |
|
|
|
fBuf.insert(0, "/"); |
|
|
|
} |
|
|
|
} |
|
|
|
// 逐层往上 倒退返回
|
|
|
|
// 逐层往上 倒退返回
|
|
|
|
treeNode = (DefaultMutableTreeNode) treeNode.getParent(); |
|
|
|
treeNode = (DefaultMutableTreeNode) treeNode.getParent(); |
|
|
|
} |
|
|
|
} |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 对文件夹进行排序 先文件夹 然后各种类型文件 |
|
|
|
* 对文件夹进行排序 先文件夹 然后各种类型文件 |
|
|
|
|
|
|
|
* |
|
|
|
* @author kunsnat |
|
|
|
* @author kunsnat |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class FileNodeComparator implements Comparator { |
|
|
|
public class FileDirectoryNodeComparator implements Comparator<FileDirectoryNode> { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* This method should return > 0 if v1 is greater than v2, 0 if |
|
|
|
* This method should return > 0 if v1 is greater than v2, 0 if |
|
|
|
* v1 is equal to v2, or < 0 if v1 is less than v2. |
|
|
|
* v1 is equal to v2, or < 0 if v1 is less than v2. |
|
|
@ -302,21 +297,19 @@ public class JFileTree extends AbstractFileTree { |
|
|
|
* @param v2 comparison value.值2 |
|
|
|
* @param v2 comparison value.值2 |
|
|
|
* @return < 0, 0, or > 0 for v1<v2, v1==v2, or v1>v2 .值1大于值2返回大于0,相等返回0,小于和大于相反 |
|
|
|
* @return < 0, 0, or > 0 for v1<v2, v1==v2, or v1>v2 .值1大于值2返回大于0,相等返回0,小于和大于相反 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public int compare(Object v1, Object v2) { |
|
|
|
@Override |
|
|
|
FileDirectoryNode nameNode1 = (FileDirectoryNode) v1; |
|
|
|
public int compare(FileDirectoryNode v1, FileDirectoryNode v2) { |
|
|
|
FileDirectoryNode nameNode2 = (FileDirectoryNode) v2; |
|
|
|
if (v1.isDirectory()) { |
|
|
|
|
|
|
|
if (v2.isDirectory()) { |
|
|
|
if (nameNode1.isDirectory()) { |
|
|
|
return v1.getName().toLowerCase().compareTo(v2.getName().toLowerCase()); |
|
|
|
if (nameNode2.isDirectory()) { |
|
|
|
|
|
|
|
return nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (nameNode2.isDirectory()) { |
|
|
|
if (v2.isDirectory()) { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); |
|
|
|
return v1.getName().toLowerCase().compareTo(v2.getName().toLowerCase()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|