From 10983cb1be957281ec251d7cb7642ac0382cac82 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Sun, 6 Apr 2003 00:00:00 +0200 Subject: [PATCH] version 0.1 * initial release --- COPYING | 340 +++++++++++++++ README | 9 + build.bat | 6 + build.sh | 8 + build.xml | 22 + build/splash.jpg | Bin 0 -> 19908 bytes src/DonkeyCore.java | 664 +++++++++++++++++++++++++++++ src/DonkeyGui.java | 229 ++++++++++ src/DownloadTableModel.java | 51 +++ src/Main.java | 9 + src/RefreshAbstractTableModel.java | 44 ++ src/ResultTableModel.java | 49 +++ src/ServerTableModel.java | 59 +++ src/TableMap.java | 73 ++++ src/TableSorter.java | 333 +++++++++++++++ src/manifest.txt | 1 + 16 files changed, 1897 insertions(+) create mode 100644 COPYING create mode 100644 README create mode 100644 build.bat create mode 100755 build.sh create mode 100644 build.xml create mode 100644 build/splash.jpg create mode 100644 src/DonkeyCore.java create mode 100644 src/DonkeyGui.java create mode 100644 src/DownloadTableModel.java create mode 100644 src/Main.java create mode 100644 src/RefreshAbstractTableModel.java create mode 100644 src/ResultTableModel.java create mode 100644 src/ServerTableModel.java create mode 100644 src/TableMap.java create mode 100644 src/TableSorter.java create mode 100644 src/manifest.txt diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README b/README new file mode 100644 index 0000000..acbaa89 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +jMoule 0.1 +site: http://royale.zerezo.com/jmoule/ +mail: royale@zerezo.com + +install: +build.bat OR ./build.sh OR ant + +usage: +java -jar dist/jMoule.jar \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8dda9b3 --- /dev/null +++ b/build.bat @@ -0,0 +1,6 @@ +SET JAVAC=javac +SET JAR=jar +%JAVAC% src/*.java -target 1.3 -d build/ +cd build +%JAR% cvfm ../dist/jMoule.jar ../src/manifest.txt . +cd .. \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5dd8ed9 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +JAVAC=javac +JAR=jar +$JAVAC src/*.java -target 1.3 -d build/ +cd build +$JAR cvfm ../dist/jMoule.jar ../src/manifest.txt . +cd .. diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..6d53508 --- /dev/null +++ b/build.xml @@ -0,0 +1,22 @@ + + + jMoule + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/splash.jpg b/build/splash.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe75caa6d49d2fa48dfc1cbdc91e77b4863b4ac3 GIT binary patch literal 19908 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 + { + String temp=new String(buffer,pos,l); + pos+=l; + return(temp); + } + else return(""); + } + + synchronized boolean sendMessage(byte[] buffer,int l) + { + try + { + connection.getOutputStream().write(l%256); + connection.getOutputStream().write(l/256); + connection.getOutputStream().write(0); + connection.getOutputStream().write(0); + connection.getOutputStream().write(buffer,0,l); + return true; + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + } + + public void connectMore() + { + byte[] buffer=new byte[2]; + buffer[0]=1; buffer[1]=0; // function + sendMessage(buffer,2); + } + + public void cleanOld() + { + byte[] buffer=new byte[2]; + buffer[0]=2; buffer[1]=0; // function + sendMessage(buffer,2); + } + + public void kill() + { + byte[] buffer=new byte[2]; + buffer[0]=3; buffer[1]=0; // function + sendMessage(buffer,2); + } + + public void extend() + { + byte[] buffer=new byte[2]; + buffer[0]=4; buffer[1]=0; // function + sendMessage(buffer,2); + } + + public void download(Long fileID) + { + byte[] buffer=new byte[9]; + int i=0; + buffer[i++]=50; buffer[i++]=0; // function + buffer[i++]=0; buffer[i++]=0; // result_names (empty list) + long id=fileID.longValue(); + for (int j=0;j<4;j++) + { + buffer[i++]=(byte)(id%256); + id/=256; + } + buffer[i++]=0; // force + sendMessage(buffer,i); + } + + public void switchDownload(Long fileID,boolean bool) + { + byte[] buffer=new byte[9]; + int i=0; + buffer[i++]=23; buffer[i++]=0; // function + long id=fileID.longValue(); + for (int j=0;j<4;j++) + { + buffer[i++]=(byte)(id%256); + id/=256; + } + if (bool) + buffer[i++]=1; + else + buffer[i++]=0; + sendMessage(buffer,i); + } + + public void connectServer(Long serverID) + { + byte[] buffer=new byte[6]; + int i=0; + buffer[i++]=21; buffer[i++]=0; // function + long id=serverID.longValue(); + for (int j=0;j<4;j++) + { + buffer[i++]=(byte)(id%256); + id/=256; + } + sendMessage(buffer,i); + } + + public void disconnectServer(Long serverID) + { + byte[] buffer=new byte[6]; + int i=0; + buffer[i++]=22; buffer[i++]=0; // function + long id=serverID.longValue(); + for (int j=0;j<4;j++) + { + buffer[i++]=(byte)(id%256); + id/=256; + } + sendMessage(buffer,i); + } + + public Vector search(String query) + { + byte[] buffer=new byte[1024*100]; + int i=0,j; + buffer[i++]=42; buffer[i++]=0; // function + buffer[i++]=(byte)(nbsearches%256); buffer[i++]=(byte)(nbsearches/256); + buffer[i++]=0; buffer[i++]=0; // num + buffer[i++]=4; // keywords + buffer[i++]=0; buffer[i++]=0; // empty string + buffer[i++]=(byte)(query.length()%256); + buffer[i++]=(byte)(query.length()/256); + for (j=0;j=2 + String host=null; + switch(readByte()) + { + case 0: + //debug("ip: "+readByte()+"."+readByte()+"."+readByte()+"."+readByte()); + host=""+readByte()+"."+readByte()+"."+readByte()+"."+readByte(); + break; + case 1: + //debug("name: "+readString()); + host=readString(); + break; + } + //debug("port: "+readInt()); + host=host+":"+readInt(); // port + serverInfo.add(host); + readLong(); // score + tags=new String(); + n=readInt(); + for (i=0;inewRowCount) + fireTableRowsDeleted(newRowCount-1,oldRowCount-1); + fireTableRowsUpdated(0,newRowCount-1); + oldRowCount=newRowCount; + */ + fireTableDataChanged(); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }; + refreshThread.start(); + } + + public Class getColumnClass(int col) + { + return getValueAt(0,col).getClass(); + } + +} \ No newline at end of file diff --git a/src/ResultTableModel.java b/src/ResultTableModel.java new file mode 100644 index 0000000..709eb8c --- /dev/null +++ b/src/ResultTableModel.java @@ -0,0 +1,49 @@ +import java.util.Hashtable; +import java.util.Vector; +import javax.swing.table.*; + +public class ResultTableModel extends RefreshAbstractTableModel +{ + + Vector searchResult; + String columns[]={"Number","File Name","Size","Tags","Download"}; + DonkeyCore donkeyCore; + + public ResultTableModel(Vector searchResult,DonkeyCore donkeyCore) + { + this.donkeyCore=donkeyCore; + this.searchResult=searchResult; + } + + public int getColumnCount() + { + return columns.length; + } + + public String getColumnName(int col) + { + return columns[col]; + } + + public int getRowCount() + { + return searchResult.size(); + } + + public Object getValueAt(int row,int col) + { + return ((Vector)searchResult.get(row)).get(col); + } + + public boolean isCellEditable(int row,int col) + { + return col==columns.length-1; + } + + public void setValueAt(Object o,int row,int col) + { + ((Vector)searchResult.get(row)).setElementAt(new Boolean(true),col); + donkeyCore.download((Long)getValueAt(row,0)); + } + +} \ No newline at end of file diff --git a/src/ServerTableModel.java b/src/ServerTableModel.java new file mode 100644 index 0000000..ac7539c --- /dev/null +++ b/src/ServerTableModel.java @@ -0,0 +1,59 @@ +import java.util.Hashtable; +import java.util.Vector; +import javax.swing.table.*; + +public class ServerTableModel extends RefreshAbstractTableModel +{ + + Hashtable serverInfos; + String columns[]={"Number","Host","Users","Files","Connected"}; + DonkeyCore donkeyCore; + + public ServerTableModel(Hashtable serverInfos,DonkeyCore donkeyCore) + { + this.donkeyCore=donkeyCore; + this.serverInfos=serverInfos; + } + + public int getColumnCount() + { + return columns.length; + } + + public String getColumnName(int col) + { + return columns[col]; + } + + public int getRowCount() + { + return serverInfos.size(); + } + + public Object getValueAt(int row,int col) + { + if (col==0) return serverInfos.keySet().toArray()[row]; + return ((Vector)serverInfos.values().toArray()[row]).get(col-1); + } + + public boolean isCellEditable(int row,int col) + { + return col==columns.length-1; + } + + public void setValueAt(Object o,int row,int col) + { + Long id=(Long)getValueAt(row,0); + Vector serverInfo=(Vector)serverInfos.get(id); + if (((Boolean)serverInfo.elementAt(3)).booleanValue()) + { + //((Vector)searchResult.get(row)).setElementAt(new Boolean(true),col); + donkeyCore.disconnectServer((Long)getValueAt(row,0)); + } + else + { + donkeyCore.connectServer((Long)getValueAt(row,0)); + } + } + +} \ No newline at end of file diff --git a/src/TableMap.java b/src/TableMap.java new file mode 100644 index 0000000..c010ddc --- /dev/null +++ b/src/TableMap.java @@ -0,0 +1,73 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/** + * In a chain of data manipulators some behaviour is common. TableMap + * provides most of this behavour and can be subclassed by filters + * that only need to override a handful of specific methods. TableMap + * implements TableModel by routing all requests to its model, and + * TableModelListener by routing all events to its listeners. Inserting + * a TableMap which has not been subclassed into a chain of table filters + * should have no effect. + * + * @version 1.8 02/06/02 + * @author Philip Milne */ + +import javax.swing.table.*; +import javax.swing.event.TableModelListener; +import javax.swing.event.TableModelEvent; + +public class TableMap extends AbstractTableModel implements TableModelListener +{ + protected TableModel model; + + public TableModel getModel() { + return model; + } + + public void setModel(TableModel model) { + this.model = model; + model.addTableModelListener(this); + } + + // By default, Implement TableModel by forwarding all messages + // to the model. + + public Object getValueAt(int aRow, int aColumn) { + return model.getValueAt(aRow, aColumn); + } + + public void setValueAt(Object aValue, int aRow, int aColumn) { + model.setValueAt(aValue, aRow, aColumn); + } + + public int getRowCount() { + return (model == null) ? 0 : model.getRowCount(); + } + + public int getColumnCount() { + return (model == null) ? 0 : model.getColumnCount(); + } + + public String getColumnName(int aColumn) { + return model.getColumnName(aColumn); + } + + public Class getColumnClass(int aColumn) { + return model.getColumnClass(aColumn); + } + + public boolean isCellEditable(int row, int column) { + return model.isCellEditable(row, column); + } +// +// Implementation of the TableModelListener interface, +// + + // By default forward all events to all the listeners. + public void tableChanged(TableModelEvent e) { + fireTableChanged(e); + } +} diff --git a/src/TableSorter.java b/src/TableSorter.java new file mode 100644 index 0000000..5fc561a --- /dev/null +++ b/src/TableSorter.java @@ -0,0 +1,333 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/** + * A sorter for TableModels. The sorter has a model (conforming to TableModel) + * and itself implements TableModel. TableSorter does not store or copy + * the data in the TableModel, instead it maintains an array of + * integers which it keeps the same size as the number of rows in its + * model. When the model changes it notifies the sorter that something + * has changed eg. "rowsAdded" so that its internal array of integers + * can be reallocated. As requests are made of the sorter (like + * getValueAt(row, col) it redirects them to its model via the mapping + * array. That way the TableSorter appears to hold another copy of the table + * with the rows in a different order. The sorting algorthm used is stable + * which means that it does not move around rows when its comparison + * function returns 0 to denote that they are equivalent. + * + * @version 1.9 02/06/02 + * @author Philip Milne + */ + +import java.util.*; + +import javax.swing.table.TableModel; +import javax.swing.event.TableModelEvent; + +// Imports for picking up mouse events from the JTable. + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.InputEvent; +import javax.swing.JTable; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class TableSorter extends TableMap +{ + int indexes[]; + Vector sortingColumns = new Vector(); + boolean ascending = true; + int compares; + int Xcolumn=0; + boolean Xascending=false; + + public TableSorter() + { + indexes = new int[0]; // For consistency. + } + + public TableSorter(TableModel model) + { + setModel(model); + } + + public void setModel(TableModel model) { + super.setModel(model); + reallocateIndexes(); + } + + public int compareRowsByColumn(int row1, int row2, int column) + { + Class type = model.getColumnClass(column); + TableModel data = model; + + // Check for nulls + + Object o1 = data.getValueAt(row1, column); + Object o2 = data.getValueAt(row2, column); + + // If both values are null return 0 + if (o1 == null && o2 == null) { + return 0; + } + else if (o1 == null) { // Define null less than everything. + return -1; + } + else if (o2 == null) { + return 1; + } + +/* We copy all returned values from the getValue call in case +an optimised model is reusing one object to return many values. +The Number subclasses in the JDK are immutable and so will not be used in +this way but other subclasses of Number might want to do this to save +space and avoid unnecessary heap allocation. +*/ + if (type.getSuperclass() == java.lang.Number.class) + { + Number n1 = (Number)data.getValueAt(row1, column); + double d1 = n1.doubleValue(); + Number n2 = (Number)data.getValueAt(row2, column); + double d2 = n2.doubleValue(); + + if (d1 > d2) + return -1; + else if (d1 < d2) + return 1; + else + return 0; + } + else if (type == java.util.Date.class) + { + Date d1 = (Date)data.getValueAt(row1, column); + long n1 = d1.getTime(); + Date d2 = (Date)data.getValueAt(row2, column); + long n2 = d2.getTime(); + + if (n1 < n2) + return -1; + else if (n1 > n2) + return 1; + else return 0; + } + else if (type == String.class) + { + String s1 = (String)data.getValueAt(row1, column); + String s2 = (String)data.getValueAt(row2, column); + int result = s1.compareTo(s2); + + if (result < 0) + return -1; + else if (result > 0) + return 1; + else return 0; + } + else if (type == Boolean.class) + { + Boolean bool1 = (Boolean)data.getValueAt(row1, column); + boolean b1 = bool1.booleanValue(); + Boolean bool2 = (Boolean)data.getValueAt(row2, column); + boolean b2 = bool2.booleanValue(); + + if (b1 == b2) + return 0; + else if (b2) // Define false > true + return 1; + else + return -1; + } + else + { + Object v1 = data.getValueAt(row1, column); + String s1 = v1.toString(); + Object v2 = data.getValueAt(row2, column); + String s2 = v2.toString(); + int result = s1.compareTo(s2); + + if (result < 0) + return -1; + else if (result > 0) + return 1; + else return 0; + } + } + + public int compare(int row1, int row2) + { + compares++; + for(int level = 0; level < sortingColumns.size(); level++) + { + Integer column = (Integer)sortingColumns.elementAt(level); + int result = compareRowsByColumn(row1, row2, column.intValue()); + if (result != 0) + return ascending ? result : -result; + } + return 0; + } + + public void reallocateIndexes() + { + int rowCount = model.getRowCount(); + + // Set up a new array of indexes with the right number of elements + // for the new data model. + indexes = new int[rowCount]; + + // Initialise with the identity mapping. + for(int row = 0; row < rowCount; row++) + indexes[row] = row; + } + + public void tableChanged(TableModelEvent e) + { + //System.out.println("Sorter: tableChanged"); + reallocateIndexes(); + + sortByColumn(Xcolumn, Xascending); + super.tableChanged(e); + } + + public void checkModel() + { + if (indexes.length != model.getRowCount()) { + //System.err.println("Sorter not informed of a change in model."); + } + } + + public void sort(Object sender) + { + checkModel(); + + compares = 0; + // n2sort(); + // qsort(0, indexes.length-1); + shuttlesort((int[])indexes.clone(), indexes, 0, indexes.length); + //System.out.println("Compares: "+compares); + } + + public void n2sort() { + for(int i = 0; i < getRowCount(); i++) { + for(int j = i+1; j < getRowCount(); j++) { + if (compare(indexes[i], indexes[j]) == -1) { + swap(i, j); + } + } + } + } + + // This is a home-grown implementation which we have not had time + // to research - it may perform poorly in some circumstances. It + // requires twice the space of an in-place algorithm and makes + // NlogN assigments shuttling the values between the two + // arrays. The number of compares appears to vary between N-1 and + // NlogN depending on the initial order but the main reason for + // using it here is that, unlike qsort, it is stable. + public void shuttlesort(int from[], int to[], int low, int high) { + if (high - low < 2) { + return; + } + int middle = (low + high)/2; + shuttlesort(to, from, low, middle); + shuttlesort(to, from, middle, high); + + int p = low; + int q = middle; + + /* This is an optional short-cut; at each recursive call, + check to see if the elements in this subset are already + ordered. If so, no further comparisons are needed; the + sub-array can just be copied. The array must be copied rather + than assigned otherwise sister calls in the recursion might + get out of sinc. When the number of elements is three they + are partitioned so that the first set, [low, mid), has one + element and and the second, [mid, high), has two. We skip the + optimisation when the number of elements is three or less as + the first compare in the normal merge will produce the same + sequence of steps. This optimisation seems to be worthwhile + for partially ordered lists but some analysis is needed to + find out how the performance drops to Nlog(N) as the initial + order diminishes - it may drop very quickly. */ + + if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) { + for (int i = low; i < high; i++) { + to[i] = from[i]; + } + return; + } + + // A normal merge. + + for(int i = low; i < high; i++) { + if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) { + to[i] = from[p++]; + } + else { + to[i] = from[q++]; + } + } + } + + public void swap(int i, int j) { + int tmp = indexes[i]; + indexes[i] = indexes[j]; + indexes[j] = tmp; + } + + // The mapping only affects the contents of the data rows. + // Pass all requests to these rows through the mapping array: "indexes". + + public Object getValueAt(int aRow, int aColumn) + { + checkModel(); + return model.getValueAt(indexes[aRow], aColumn); + } + + public void setValueAt(Object aValue, int aRow, int aColumn) + { + checkModel(); + model.setValueAt(aValue, indexes[aRow], aColumn); + } + + public void sortByColumn(int column) { + sortByColumn(column, true); + } + + public void sortByColumn(int column, boolean ascending) { + this.ascending = ascending; + sortingColumns.removeAllElements(); + sortingColumns.addElement(new Integer(column)); + sort(this); + super.tableChanged(new TableModelEvent(this)); + } + + // There is no-where else to put this. + // Add a mouse listener to the Table to trigger a table sort + // when a column heading is clicked in the JTable. + public void addMouseListenerToHeaderInTable(JTable table) { + final TableSorter sorter = this; + final JTable tableView = table; + tableView.setColumnSelectionAllowed(false); + MouseAdapter listMouseListener = new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + TableColumnModel columnModel = tableView.getColumnModel(); + int viewColumn = columnModel.getColumnIndexAtX(e.getX()); + int column = tableView.convertColumnIndexToModel(viewColumn); + if(e.getClickCount() == 1 && column != -1) { + //System.out.println("Sorting ..."); + int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; + boolean ascending = (shiftPressed == 0); + sorter.sortByColumn(Xcolumn=column, Xascending=ascending); + } + } + }; + JTableHeader th = tableView.getTableHeader(); + th.addMouseListener(listMouseListener); + } + + + +} diff --git a/src/manifest.txt b/src/manifest.txt new file mode 100644 index 0000000..26029e3 --- /dev/null +++ b/src/manifest.txt @@ -0,0 +1 @@ +Main-Class: Main -- 2.20.1