Changeset 7909

Show
Ignore:
Timestamp:
04/02/07 15:59:53 (22 months ago)
Author:
jburke
Message:

(merge from 0.4 branch) Fixes #2407 and Refs #2386. dojo compressing now works over multiple files in the same process. Layer files are now compressed, and it is possible to compress all files in the src directory

Location:
util/trunk/buildscripts
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • util/trunk/buildscripts/build.js

    r7881 r7909  
    170170 
    171171                        //Save compressed file. 
    172                         //FIXME: this probably breaks with multiple layers -- it seems like an issue 
    173                         //inside the compressor. 
    174172                        var compresedContents = buildUtil.optimizeJs(fileName, fileContents, layerLegalText, true); 
    175173                        fileUtil.saveFile(fileName, compresedContents); 
     
    224222 
    225223        } 
     224         
     225        //FIXME: call stripComments. Maybe rename, inline with optimize? need build options too. 
    226226} 
    227227//********* End _releasePrefixPath ********* 
  • util/trunk/buildscripts/jslib/buildUtil.js

    r7898 r7909  
    734734} 
    735735 
    736 buildUtil.stripComments = function(/*String*/startDir, /*boolean*/suppressDojoCopyright){ 
     736buildUtil.stripComments = function(/*String*/startDir, /*boolean*/suppressDojoCopyright, /*boolean*/doCompress){ 
    737737        //summary: strips the JS comments from all the files in "startDir", and all subdirectories. 
    738738        var copyright = suppressDojoCopyright ? "" : (fileUtil.readFile("copyright.txt") + fileUtil.getLineSeparator()); 
     
    754754                                //Do comment removal. 
    755755                                try{ 
    756                                         fileContents = buildUtil.optimizeJs(fileList[i], fileContents, copyright, false); 
     756                                        fileContents = buildUtil.optimizeJs(fileList[i], fileContents, copyright, doCompress); 
    757757                                }catch(e){ 
    758758                                        print("Could not strip comments for file: " + fileList[i] + ", error: " + e); 
  • util/trunk/buildscripts/lib/custom_rhino.diff

    r6681 r7909  
    1 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/BaseFunction.java rhino1_6R4/src/org/mozilla/javascript/BaseFunction.java 
    2 --- rhino/src/org/mozilla/javascript/BaseFunction.java  2006-09-09 13:14:10.000000000 -0400 
    3 +++ rhino1_6R4/src/org/mozilla/javascript/BaseFunction.java     2006-09-27 17:03:18.000000000 -0400 
     1### Eclipse Workspace Patch 1.0 
     2#P rhino 
     3Index: src/org/mozilla/javascript/BaseFunction.java 
     4=================================================================== 
     5RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/BaseFunction.java,v 
     6retrieving revision 1.57 
     7diff -u -r1.57 BaseFunction.java 
     8--- src/org/mozilla/javascript/BaseFunction.java        30 Aug 2005 10:05:42 -0000      1.57 
     9+++ src/org/mozilla/javascript/BaseFunction.java        2 Apr 2007 22:06:50 -0000 
    410@@ -373,6 +373,28 @@ 
    511         return sb.toString(); 
     
    3137  
    3238     public int getLength() { return 0; } 
    33 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/BaseFunction.java.rej rhino1_6R4/src/org/mozilla/javascript/BaseFunction.java.rej 
    34 --- rhino/src/org/mozilla/javascript/BaseFunction.java.rej      1969-12-31 19:00:00.000000000 -0500 
    35 +++ rhino1_6R4/src/org/mozilla/javascript/BaseFunction.java.rej 2006-09-27 17:08:59.000000000 -0400 
    36 @@ -0,0 +1,37 @@ 
    37 +*************** 
    38 +*** 373,378 **** 
    39 +          return sb.toString(); 
    40 +      } 
    41  
    42 +      public int getArity() { return 0; } 
    43  
    44 +      public int getLength() { return 0; } 
    45 +--- 373,400 ---- 
    46 +          return sb.toString(); 
    47 +      } 
    48  
    49 ++         String compress(int indent, int flags) 
    50 ++         { 
    51 ++             StringBuffer sb = new StringBuffer(); 
    52 ++              String FuncName = null; 
    53 ++             boolean justbody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); 
    54 ++             if (!justbody) { 
    55 ++                 sb.append("function"); 
    56 ++                      FuncName = getFunctionName(); 
    57 ++                      if(FuncName.length()>0){ 
    58 ++                              sb.append(" "+FuncName); 
    59 ++                      } 
    60 ++                 sb.append("(){"); 
    61 ++             } 
    62 ++            sb.append("[native code, arity="); 
    63 ++             sb.append(getArity()); 
    64 ++             sb.append("]"); 
    65 ++             if (!justbody) { 
    66 ++                 sb.append("}"); 
    67 ++             } 
    68 ++             return sb.toString(); 
    69 ++         } 
    70 ++      
    71 +      public int getArity() { return 0; } 
    72  
    73 +      public int getLength() { return 0; } 
    74 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/Context.java rhino1_6R4/src/org/mozilla/javascript/Context.java 
    75 --- rhino/src/org/mozilla/javascript/Context.java       2006-09-09 13:14:10.000000000 -0400 
    76 +++ rhino1_6R4/src/org/mozilla/javascript/Context.java  2006-09-27 17:03:18.000000000 -0400 
     39Index: src/org/mozilla/javascript/NativeFunction.java 
     40=================================================================== 
     41RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/NativeFunction.java,v 
     42retrieving revision 1.62 
     43diff -u -r1.62 NativeFunction.java 
     44--- src/org/mozilla/javascript/NativeFunction.java      17 Jan 2005 13:06:33 -0000      1.62 
     45+++ src/org/mozilla/javascript/NativeFunction.java      2 Apr 2007 22:06:50 -0000 
     46@@ -70,6 +70,26 @@ 
     47         } 
     48     } 
     49  
     50+    /** 
     51+     * Compress the script. 
     52+     * <p> 
     53+     *  
     54+     * @param parseTree Mapping for each function node and corresponding parameters & variables names 
     55+     * @param indent How much to indent the decompiled result 
     56+     * @param flags Flags specifying format of decompilation output 
     57+     * @return compressed script 
     58+     */ 
     59+    final String compress(ScriptOrFnNode parseTree, int indent, int flags) 
     60+    { 
     61+        String encodedSource = getEncodedSource(); 
     62+        if (encodedSource == null) { 
     63+            return super.compress(indent, flags); 
     64+        } else { 
     65+            UintMap properties = new UintMap(1); 
     66+            properties.put(Decompiler.INITIAL_INDENT_PROP, indent); 
     67+            return Decompiler.compress(encodedSource, flags, properties, parseTree); 
     68+        } 
     69+    } 
     70     public int getLength() 
     71     { 
     72         int paramCount = getParamCount(); 
     73Index: src/org/mozilla/javascript/TokenStream.java 
     74=================================================================== 
     75RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/TokenStream.java,v 
     76retrieving revision 1.63 
     77diff -u -r1.63 TokenStream.java 
     78--- src/org/mozilla/javascript/TokenStream.java 31 Jul 2005 13:48:46 -0000      1.63 
     79+++ src/org/mozilla/javascript/TokenStream.java 2 Apr 2007 22:06:50 -0000 
     80@@ -64,9 +64,12 @@ 
     81     private final static int 
     82         EOF_CHAR = -1; 
     83  
     84+    public StringBuffer lastComment; 
     85+     
     86     TokenStream(Parser parser, Reader sourceReader, String sourceString, 
     87                 int lineno) 
     88     { 
     89+       this.lastComment = new StringBuffer(); 
     90         this.parser = parser; 
     91         this.lineno = lineno; 
     92         if (sourceReader != null) { 
     93@@ -736,6 +739,8 @@ 
     94  
     95             case '/': 
     96                 // is it a // comment? 
     97+               // FIXME: RAR: comment, need to set config to optionally keep 
     98+               // instead of skipping! 
     99                 if (matchChar('/')) { 
     100                     skipLine(); 
     101                     continue retry; 
     102Index: src/org/mozilla/javascript/Context.java 
     103=================================================================== 
     104RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Context.java,v 
     105retrieving revision 1.244 
     106diff -u -r1.244 Context.java 
     107--- src/org/mozilla/javascript/Context.java     4 Nov 2005 13:37:45 -0000       1.244 
     108+++ src/org/mozilla/javascript/Context.java     2 Apr 2007 22:06:50 -0000 
    77109@@ -1178,6 +1178,33 @@ 
    78110         } 
     
    109141      * Check whether a string is ready to be compiled. 
    110142      * <p> 
    111 @@ -1361,6 +1388,27 @@ 
     143@@ -1361,6 +1388,33 @@ 
    112144     } 
    113145  
     
    123155+    public final String compressScript(Script script, int indent, String source,int lineno) 
    124156+    { 
     157+        //Make sure to clear out the TokenMapper state before running. 
     158+        //This allows for more than one script to be compressed. 
     159+        //However, this is not a very clean way to do the reset. 
     160+        TokenMapper.reset(); 
     161+        Decompiler.tm = new TokenMapper(); 
     162+ 
    125163+        NativeFunction scriptImpl = (NativeFunction) script; 
    126164+         
     
    137175      * <p> 
    138176      * Decompiles a previously compiled JavaScript function object to 
    139 @@ -2240,7 +2288,6 @@ 
     177@@ -2240,7 +2294,6 @@ 
    140178                 sourceReader = null; 
    141179             } 
     
    145183         if (returnFunction) { 
    146184             p.calledByCompileFunction = true; 
    147 @@ -2251,6 +2298,7 @@ 
     185@@ -2251,6 +2304,7 @@ 
    148186         } else { 
    149187             tree = p.parse(sourceReader, sourceName, lineno); 
     
    153191             if (!(tree.getFunctionCount() == 1 
    154192                   && tree.getFirstChild() != null 
    155 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/Decompiler.java rhino1_6R4/src/org/mozilla/javascript/Decompiler.java 
    156 --- rhino/src/org/mozilla/javascript/Decompiler.java    2006-09-09 13:14:10.000000000 -0400 
    157 +++ rhino1_6R4/src/org/mozilla/javascript/Decompiler.java       2006-09-27 17:03:18.000000000 -0400 
     193Index: src/org/mozilla/javascript/Decompiler.java 
     194=================================================================== 
     195RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/Decompiler.java,v 
     196retrieving revision 1.19 
     197diff -u -r1.19 Decompiler.java 
     198--- src/org/mozilla/javascript/Decompiler.java  28 Aug 2005 23:25:22 -0000      1.19 
     199+++ src/org/mozilla/javascript/Decompiler.java  2 Apr 2007 22:06:50 -0000 
    158200@@ -37,6 +37,11 @@ 
    159201  
     
    168210  * The following class save decompilation information about the source. 
    169211  * Source information is returned from the parser as a String 
    170 @@ -70,6 +75,264 @@ 
     212@@ -70,6 +75,272 @@ 
    171213  * the final constant pool entry from information available at parse 
    172214  * time. 
     
    198240+ 
    199241+       private int lastTokenCount = 0; 
     242+ 
     243+       /** 
     244+        * Reset the static members for the TokenMapper. 
     245+        */ 
     246+       public static void reset() { 
     247+               funcObjects = new ObjArray(); 
     248+               functionVarMappings = new ArrayList(); 
     249+       } 
    200250+ 
    201251+       /** 
     
    433483 { 
    434484     /** 
    435 @@ -266,6 +529,512 @@ 
     485@@ -266,6 +537,515 @@ 
    436486         return new String(sourceBuffer, offset, sourceTop - offset); 
    437487     } 
    438488  
    439 +    private static TokenMapper tm = new TokenMapper(); 
     489+    //Used to be private, but making it public so we 
     490+    //can reset the token state between compression runs. 
     491+    //Not very pretty. 
     492+    public static TokenMapper tm = new TokenMapper(); 
    440493+     
    441494+    /** 
     
    946999      * Decompile the source information associated with this js 
    9471000      * function/script back into a string.  For the most part, this 
    948 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/NativeFunction.java rhino1_6R4/src/org/mozilla/javascript/NativeFunction.java 
    949 --- rhino/src/org/mozilla/javascript/NativeFunction.java        2006-09-09 13:14:10.000000000 -0400 
    950 +++ rhino1_6R4/src/org/mozilla/javascript/NativeFunction.java   2006-09-27 17:03:18.000000000 -0400 
    951 @@ -70,6 +70,26 @@ 
    952          } 
    953      } 
    954   
    955 +    /** 
    956 +     * Compress the script. 
    957 +     * <p> 
    958 +     *  
    959 +     * @param parseTree Mapping for each function node and corresponding parameters & variables names 
    960 +     * @param indent How much to indent the decompiled result 
    961 +     * @param flags Flags specifying format of decompilation output 
    962 +     * @return compressed script 
    963 +     */ 
    964 +    final String compress(ScriptOrFnNode parseTree, int indent, int flags) 
    965 +    { 
    966 +        String encodedSource = getEncodedSource(); 
    967 +        if (encodedSource == null) { 
    968 +            return super.compress(indent, flags); 
    969 +        } else { 
    970 +            UintMap properties = new UintMap(1); 
    971 +            properties.put(Decompiler.INITIAL_INDENT_PROP, indent); 
    972 +            return Decompiler.compress(encodedSource, flags, properties, parseTree); 
    973 +        } 
    974 +    } 
    975      public int getLength() 
    976      { 
    977          int paramCount = getParamCount(); 
    978 diff -Naur -x '*.jar' rhino/src/org/mozilla/javascript/TokenStream.java rhino1_6R4/src/org/mozilla/javascript/TokenStream.java 
    979 --- rhino/src/org/mozilla/javascript/TokenStream.java   2006-09-09 13:14:10.000000000 -0400 
    980 +++ rhino1_6R4/src/org/mozilla/javascript/TokenStream.java      2006-09-27 17:03:18.000000000 -0400 
    981 @@ -64,9 +64,12 @@ 
    982      private final static int 
    983          EOF_CHAR = -1; 
    984   
    985 +    public StringBuffer lastComment; 
    986 +     
    987      TokenStream(Parser parser, Reader sourceReader, String sourceString, 
    988                  int lineno) 
    989      { 
    990 +       this.lastComment = new StringBuffer(); 
    991          this.parser = parser; 
    992          this.lineno = lineno; 
    993          if (sourceReader != null) { 
    994 @@ -736,6 +739,8 @@ 
    995   
    996              case '/': 
    997                  // is it a // comment? 
    998 +               // FIXME: RAR: comment, need to set config to optionally keep 
    999 +               // instead of skipping! 
    1000                  if (matchChar('/')) { 
    1001                      skipLine(); 
    1002                      continue retry; 
    1003 diff -Naur -x '*.jar' rhino/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/AbstractCellEditor.java rhino1_6R4/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/AbstractCellEditor.java 
    1004 --- rhino/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/AbstractCellEditor.java      1969-12-31 19:00:00.000000000 -0500 
    1005 +++ rhino1_6R4/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/AbstractCellEditor.java 2006-09-27 17:04:27.000000000 -0400 
    1006 @@ -0,0 +1,63 @@ 
    1007 + 
    1008 +         package org.mozilla.javascript.tools.debugger.downloaded; 
    1009 +         import java.awt.Component; 
    1010 +        
    1011 +import java.awt.event.*; 
    1012 +import java.awt.AWTEvent; 
    1013 +import javax.swing.*; 
    1014 +import javax.swing.event.*; 
    1015 +import java.util.EventObject; 
    1016 +import java.io.Serializable; 
    1017 + 
    1018 +public class AbstractCellEditor implements CellEditor { 
    1019 + 
    1020 +    protected EventListenerList listenerList = new EventListenerList(); 
    1021 + 
    1022 +    public Object getCellEditorValue() { return null; } 
    1023 +    public boolean isCellEditable(EventObject e) { return true; } 
    1024 +    public boolean shouldSelectCell(EventObject anEvent) { return false; } 
    1025 +    public boolean stopCellEditing() { return true; } 
    1026 +    public void cancelCellEditing() {} 
    1027 + 
    1028 +    public void addCellEditorListener(CellEditorListener l) { 
    1029 +       listenerList.add(CellEditorListener.class, l); 
    1030 +    } 
    1031 + 
    1032 +    public void removeCellEditorListener(CellEditorListener l) { 
    1033 +       listenerList.remove(CellEditorListener.class, l); 
    1034 +    } 
    1035 + 
    1036 +    /* 
    1037 +     * Notify all listeners that have registered interest for 
    1038 +     * notification on this event type.   
    1039 +     * @see EventListenerList 
    1040 +     */ 
    1041 +    protected void fireEditingStopped() { 
    1042 +       // Guaranteed to return a non-null array 
    1043 +       Object[] listeners = listenerList.getListenerList(); 
    1044 +       // Process the listeners last to first, notifying 
    1045 +       // those that are interested in this event 
    1046 +       for (int i = listeners.length-2; i>=0; i-=2) { 
    1047 +           if (listeners[i]==CellEditorListener.class) { 
    1048 +               ((CellEditorListener)listeners[i+1]).editingStopped(new ChangeEvent(this)); 
    1049 +           }           
    1050 +       } 
    1051 +    } 
    1052 + 
    1053 +    /* 
    1054 +     * Notify all listeners that have registered interest for 
    1055 +     * notification on this event type.   
    1056 +     * @see EventListenerList 
    1057 +     */ 
    1058 +    protected void fireEditingCanceled() { 
    1059 +       // Guaranteed to return a non-null array 
    1060 +       Object[] listeners = listenerList.getListenerList(); 
    1061 +       // Process the listeners last to first, notifying 
    1062 +       // those that are interested in this event 
    1063 +       for (int i = listeners.length-2; i>=0; i-=2) { 
    1064 +           if (listeners[i]==CellEditorListener.class) { 
    1065 +               ((CellEditorListener)listeners[i+1]).editingCanceled(new ChangeEvent(this)); 
    1066 +           }           
    1067 +       } 
    1068 +    } 
    1069 +} 
    1070 diff -Naur -x '*.jar' rhino/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/JTreeTable.java rhino1_6R4/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/JTreeTable.java 
    1071 --- rhino/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/JTreeTable.java      1969-12-31 19:00:00.000000000 -0500 
    1072 +++ rhino1_6R4/toolsrc/org/mozilla/javascript/tools/debugger/downloaded/JTreeTable.java 2006-09-27 17:04:27.000000000 -0400 
    1073 @@ -0,0 +1,356 @@ 
    1074 +/* 
    1075 + * @(#)JTreeTable.java 1.2 98/10/27 
    1076 + * 
    1077 + * Copyright 1997, 1998 by Sun Microsystems, Inc., 
    1078 + * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. 
    1079 + * All rights reserved. 
    1080 + * 
    1081 + * This software is the confidential and proprietary information 
    1082 + * of Sun Microsystems, Inc. ("Confidential Information").  You 
    1083 + * shall not disclose such Confidential Information and shall use 
    1084 + * it only in accordance with the terms of the license agreement 
    1085 + * you entered into with Sun. 
    1086 + */ 
    1087 + 
    1088 + 
    1089 +         package org.mozilla.javascript.tools.debugger.downloaded; 
    1090 +         import javax.swing.*; 
    1091 +        
    1092 +import javax.swing.event.*; 
    1093 +import javax.swing.tree.*; 
    1094 +import javax.swing.table.*; 
    1095 + 
    1096 +import java.awt.Dimension; 
    1097 +import java.awt.Component; 
    1098 +import java.awt.Graphics; 
    1099 +import java.awt.Rectangle; 
    1100 + 
    1101 +import java.awt.event.MouseEvent; 
    1102 + 
    1103 +import java.util.EventObject; 
    1104 + 
    1105 +/** 
    1106 + * This example shows how to create a simple JTreeTable component,  
    1107 + * by using a JTree as a renderer (and editor) for the cells in a  
    1108 + * particular column in the JTable.   
    1109 + * 
    1110 + * @version 1.2 10/27/98 
    1111 + * 
    1112 + * @author Philip Milne 
    1113 + * @author Scott Violet 
    1114 + */ 
    1115 +public class JTreeTable extends JTable { 
    1116 +    /** A subclass of JTree. */ 
    1117 +    protected TreeTableCellRenderer tree; 
    1118 + 
    1119 +    public JTreeTable(TreeTableModel treeTableModel) { 
    1120 +       super(); 
    1121 + 
    1122 +       // Create the tree. It will be used as a renderer and editor.  
    1123 +       tree = new TreeTableCellRenderer(treeTableModel); 
    1124 + 
    1125 +       // Install a tableModel representing the visible rows in the tree.  
    1126 +       super.setModel(new TreeTableModelAdapter(treeTableModel, tree)); 
    1127 + 
    1128 +       // Force the JTable and JTree to share their row selection models.  
    1129 +       ListToTreeSelectionModelWrapper selectionWrapper = new  
    1130 +                               ListToTreeSelectionModelWrapper(); 
    1131 +       tree.setSelectionModel(selectionWrapper); 
    1132 +       setSelectionModel(selectionWrapper.getListSelectionModel());  
    1133 + 
    1134 +       // Install the tree editor renderer and editor.  
    1135 +       setDefaultRenderer(TreeTableModel.class, tree);  
    1136 +       setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor()); 
    1137 + 
    1138 +       // No grid. 
    1139 +       setShowGrid(false); 
    1140 + 
    1141 +       // No intercell spacing 
    1142 +       setIntercellSpacing(new Dimension(0, 0));        
    1143 + 
    1144 +       // And update the height of the trees row to match that of 
    1145 +       // the table. 
    1146 +       if (tree.getRowHeight() < 1) { 
    1147 +           // Metal looks better like this. 
    1148 +           setRowHeight(18); 
    1149 +       } 
    1150 +    } 
    1151 + 
    1152 +    /** 
    1153 +     * Overridden to message super and forward the method to the tree. 
    1154 +     * Since the tree is not actually in the component hieachy it will 
    1155 +     * never receive this unless we forward it in this manner. 
    1156 +     */ 
    1157 +    public void updateUI() { 
    1158 +       super.updateUI(); 
    1159 +       if(tree != null) { 
    1160 +           tree.updateUI(); 
    1161 +       } 
    1162 +       // Use the tree's default foreground and background colors in the 
    1163 +       // table.  
    1164 +        LookAndFeel.installColorsAndFont(this, "Tree.background", 
    1165 +                                         "Tree.foreground", "Tree.font"); 
    1166 +    } 
    1167 + 
    1168 +    /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to  
    1169 +     * paint the editor. The UI currently uses different techniques to  
    1170 +     * paint the renderers and editors and overriding setBounds() below  
    1171 +     * is not the right thing to do for an editor. Returning -1 for the  
    1172 +     * editing row in this case, ensures the editor is never painted.  
    1173 +     */ 
    1174 +    public int getEditingRow() { 
    1175 +        return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 : 
    1176 +               editingRow;   
    1177 +    } 
    1178 + 
    1179 +    /** 
    1180 +     * Overridden to pass the new rowHeight to the tree. 
    1181 +     */ 
    1182 +    public void setRowHeight(int rowHeight) {  
    1183 +        super.setRowHeight(rowHeight);  
    1184 +       if (tree != null && tree.getRowHeight() != rowHeight) { 
    1185 +            tree.setRowHeight(getRowHeight());  
    1186 +       } 
    1187 +    } 
    1188 + 
    1189 +    /** 
    1190 +     * Returns the tree that is being shared between the model. 
    1191 +     */ 
    1192 +    public JTree getTree() { 
    1193 +       return tree; 
    1194 +    } 
    1195 + 
    1196 +    /** 
    1197 +     * A TreeCellRenderer that displays a JTree. 
    1198 +     */ 
    1199 +    public class TreeTableCellRenderer extends JTree implements 
    1200 +                TableCellRenderer { 
    1201 +       /** Last table/tree row asked to renderer. */ 
    1202 +       protected int visibleRow; 
    1203 + 
    1204 +       public TreeTableCellRenderer(TreeModel model) { 
    1205 +           super(model);  
    1206 +       } 
    1207 + 
    1208 +       /** 
    1209 +        * updateUI is overridden to set the colors of the Tree's renderer 
    1210 +        * to match that of the table. 
    1211 +        */ 
    1212 +       public void updateUI() { 
    1213 +           super.updateUI(); 
    1214 +           // Make the tree's cell renderer use the table's cell selection 
    1215 +           // colors.  
    1216 +           TreeCellRenderer tcr = getCellRenderer(); 
    1217 +           if (tcr instanceof DefaultTreeCellRenderer) { 
    1218 +               DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);  
    1219 +               // For 1.1 uncomment this, 1.2 has a bug that will cause an 
    1220 +               // exception to be thrown if the border selection color is 
    1221 +               // null. 
    1222 +               // dtcr.setBorderSelectionColor(null); 
    1223 +               dtcr.setTextSelectionColor(UIManager.getColor 
    1224 +                                          ("Table.selectionForeground")); 
    1225 +               dtcr.setBackgroundSelectionColor(UIManager.getColor 
    1226 +                                               ("Table.selectionBackground")); 
    1227 +           } 
    1228 +       } 
    1229 + 
    1230 +       /** 
    1231 +        * Sets the row height of the tree, and forwards the row height to 
    1232 +        * the table. 
    1233 +        */ 
    1234 +       public void setRowHeight(int rowHeight) {  
    1235 +           if (rowHeight > 0) { 
    1236 +               super.setRowHeight(rowHeight);  
    1237 +               if (JTreeTable.this != null && 
    1238 +                   JTreeTable.this.getRowHeight() != rowHeight) { 
    1239 +                   JTreeTable.this.setRowHeight(getRowHeight());  
    1240 +               } 
    1241 +           } 
    1242 +       } 
    1243 + 
    1244 +       /** 
    1245 +        * This is overridden to set the height to match that of the JTable. 
    1246 +        */ 
    1247 +       public void setBounds(int x, int y, int w, int h) { 
    1248 +           super.setBounds(x, 0, w, JTreeTable.this.getHeight()); 
    1249 +       } 
    1250 + 
    1251 +       /** 
    1252 +        * Sublcassed to translate the graphics such that the last visible 
    1253 +        * row will be drawn at 0,0. 
    1254 +        */ 
    1255 +       public void paint(Graphics g) { 
    1256 +           g.translate(0, -visibleRow * getRowHeight()); 
    1257 +           super.paint(g); 
    1258 +       } 
    1259 + 
    1260 +       /** 
    1261 +        * TreeCellRenderer method. Overridden to update the visible row. 
    1262 +        */ 
    1263 +       public Component getTableCellRendererComponent(JTable table, 
    1264 +                                                      Object value, 
    1265 +                                                      boolean isSelected, 
    1266 +                                                      boolean hasFocus, 
    1267 +                                                      int row, int column) { 
    1268 +           if(isSelected) 
    1269 +               setBackground(table.getSelectionBackground()); 
    1270 +           else 
    1271 +               setBackground(table.getBackground()); 
    1272 + 
    1273 +           visibleRow = row; 
    1274 +           return this; 
    1275 +       } 
    1276 +    } 
    1277 + 
    1278 + 
    1279 +    /** 
    1280 +     * TreeTableCellEditor implementation. Component returned is the 
    1281 +     * JTree. 
    1282 +     */ 
    1283 +    public class TreeTableCellEditor extends AbstractCellEditor implements 
    1284 +                TableCellEditor { 
    1285 +       public Component getTableCellEditorComponent(JTable table, 
    1286 +                                                    Object value, 
    1287 +                                                    boolean isSelected, 
    1288 +                                                    int r, int c) { 
    1289 +           return tree; 
    1290 +       } 
    1291 + 
    1292 +       /** 
    1293 +        * Overridden to return false, and if the event is a mouse event 
    1294 +        * it is forwarded to the tree.<p> 
    1295 +        * The behavior for this is debatable, and should really be offered 
    1296 +        * as a property. By returning false, all keyboard actions are 
    1297 +        * implemented in terms of the table. By returning true, the 
    1298 +        * tree would get a chance to do something with the keyboard 
    1299 +        * events. For the most part this is ok. But for certain keys, 
    1300 +        * such as left/right, the tree will expand/collapse where as 
    1301 +        * the table focus should really move to a different column. Page 
    1302 +        * up/down should also be implemented in terms of the table. 
    1303 +        * By returning false this also has the added benefit that clicking 
    1304 +        * outside of the bounds of the tree node, but still in the tree 
    1305 +        * column will select the row, whereas if this returned true 
    1306 +        * that wouldn't be the case. 
    1307 +        * <p>By returning false we are also enforcing the policy that 
    1308 +        * the tree will never be editable (at least by a key sequence). 
    1309 +        */ 
    1310 +       public boolean isCellEditable(EventObject e) { 
    1311 +           if (e instanceof MouseEvent) { 
    1312 +               for (int counter = getColumnCount() - 1; counter >= 0; 
    1313 +                    counter--) { 
    1314 +                   if (getColumnClass(counter) == TreeTableModel.class) { 
    1315 +                       MouseEvent me = (MouseEvent)e; 
    1316 +                       MouseEvent newME = new MouseEvent(tree, me.getID(), 
    1317 +                                  me.getWhen(), me.getModifiers(), 
    1318 +                                  me.getX() - getCellRect(0, counter, true).x, 
    1319 +                                  me.getY(), me.getClickCount(), 
    1320 +                                   me.isPopupTrigger()); 
    1321 +                       tree.dispatchEvent(newME); 
    1322 +                       break; 
    1323 +                   } 
    1324 +               } 
    1325 +           } 
    1326 +           return false; 
    1327 +       } 
    1328 +    } 
    1329 + 
    1330 + 
    1331 +    /** 
    1332 +     * ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel 
    1333 +     * to listen for changes in the ListSelectionModel it maintains. Once 
    1334 +     * a change in the ListSelectionModel happens, the paths are updated 
    1335 +     * in the DefaultTreeSelectionModel. 
    1336 +     */ 
    1337 +    public class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel {  
    1338 +       /** Set to true when we are updating the ListSelectionModel. */ 
    1339 +       protected boolean         updatingListSelectionModel; 
    1340 + 
    1341 +       public ListToTreeSelectionModelWrapper() { 
    1342 +           super(); 
    1343 +           getListSelectionModel().addListSelectionListener 
    1344 +                                   (createListSelectionListener()); 
    1345 +       } 
    1346 + 
    1347 +       /** 
    1348 +        * Returns the list selection model. ListToTreeSelectionModelWrapper 
    1349 +        * listens for changes to this model and updates the selected paths 
    1350 +        * accordingly. 
    1351 +        */ 
    1352 +       public ListSelectionModel getListSelectionModel() { 
    1353 +           return listSelectionModel;  
    1354 +       } 
    1355 + 
    1356 +       /** 
    1357 +        * This is overridden to set <code>updatingListSelectionModel</code></