package p4jdb ; import java.awt.* ; import java.awt.event.* ; import java.util.* ; /** * Yet another Java object that displays a directory tree. * The main differences, apart from that I wrote it myself (NIH ;^) ) * is that it is tested with large trees (>20k entries) and does not * bother with images and other fancy stuff. The need for speed..... * <br> * The class defines two interfaces, <tt>TreeDisplay::Data</tt> and * <tt>TreeDisplay::DataManager</tt>, that connects the display to the * data. The constructor takes a <tt>TreeDisplay::DataManager</tt> * object that provides an interface to <tt>TreeDisplay::Data</tt> * objects. <br> * <i>/Fredric</i><br> * PS. It is also my first java ever so be gentle.... */ public class TreeDisplay extends Panel implements AdjustmentListener { /** * Represents a data item displayed in the tree (typically a file) * <br> * The data for the object is displayed on a line */ public interface Data { /** * Draw a line representing a data object. *@param height Line height *@param p Start point (lower right) *@param g Graphics object to use *@return width of object drawn in pixels (or 0 if no object). The * width is used to determine clickable area for the object. */ public int draw(int height, Point p, Graphics g) ; /** * Get level in tree *@return level in tree (number of tics to indent) */ public int level() ; /** * This member is called when the mouse has been clicked on the * line. *@param cp Component where object is drawn *@param pt Point within component where mouse is clicked *@param rpt Point relative to position given in draw() metod */ public void mouseClicked(Component cp, Point pt, Point rpt) ; } ; /** * Interface for an object that manages the data items (typically a file * structure) */ public interface DataManager { /** * Used by <tt>TreeDisplay</tt> to get the total number of * lines to display. *@return Number of lines (items) to display */ public int getLines() ; /** * Get Data object by offset *@param offset Offset of object to return *@return Item at specified offset *@throws IndexOutOfBoundsException if offset out of bounds */ public Data getItemAt(int offset) throws java.lang.IndexOutOfBoundsException ; /** * Get line height. Current implementation assumes same height * for all lines. *@return line height in pixels */ public int getLineHeight() ; /** * Get indent value *@return number of pixels to indent for each level in tree */ public int indentValue() ; /** * Get background color for panel *@return background color */ public Color getBackground() ; /** * Called before repaint. The idea is to give the <tt>DataManager</tt> * object a chance to prepare itself before data is painted. */ public void prePaint() ; } ; private DataManager theDataManager_ ; /** * Contains data for a line */ private class LineData { /** * Min and max x/y positions */ public int minY,maxY,minX,maxX ; /** * Data object */ public Data data ; } ; private Vector lineDataV_ = new Vector() ; /** * Internal class that represents a panel */ private class MyPanel extends Panel { public Image offScreenImage ; public void paint(Graphics graphics) { if(offScreenImage == null) { TreeDisplay.this.paint(TreeDisplay.this.getGraphics()) ; } graphics.drawImage(offScreenImage,0,0,this) ; } } ; /** * Graphic objects */ //private Scrollbar hadj_ ; private Scrollbar vadj_ ; private MyPanel panel_ ; /** * No. of top line in window */ private int firstLineNo_ ; /** * Constructor *@param dataManager DataManager object */ public TreeDisplay(DataManager dataManager) { theDataManager_ = dataManager ; firstLineNo_ = 0 ; // Create graphic objects panel_ = new MyPanel() ; //hadj_ = new Scrollbar(Scrollbar.HORIZONTAL) ; vadj_ = new Scrollbar(Scrollbar.VERTICAL) ; // Re-direct mouseclicks to parent class panel_.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { TreeDisplay.this.mouseClicked(e) ; } }) ; // Make object listen to scrollbars //hadj_.addAdjustmentListener(this) ; vadj_.addAdjustmentListener(this) ; // Define a layout GridBagLayout gridbag = new GridBagLayout() ; setLayout(gridbag) ; GridBagConstraints c = new GridBagConstraints(); // Define layout for panel and add object c.fill = GridBagConstraints.BOTH ; c.weightx = 1; c.weighty = 1; c.gridwidth = GridBagConstraints.RELATIVE ; c.gridheight = GridBagConstraints.RELATIVE ; gridbag.setConstraints(panel_,c) ; add(panel_) ; // Define layout for vertical scrollbar and // add object c.weightx = 0; c.weighty = 0; c.gridwidth = GridBagConstraints.REMAINDER ; c.gridheight = GridBagConstraints.RELATIVE ; gridbag.setConstraints(vadj_,c) ; add(vadj_) ; // Define layout for horizontal scrollbar and // add object //c.gridwidth = GridBagConstraints.RELATIVE ; //c.gridheight = GridBagConstraints.REMAINDER ; //gridbag.setConstraints(hadj_,c) ; //add(hadj_) ; panel_.setBackground(theDataManager_.getBackground()) ; } ; /** * <B>NOTE!</B> Should really be private, bug in java<br> * handle mouse click */ public void mouseClicked(MouseEvent event) { int y = event.getPoint().y ; Enumeration e = lineDataV_.elements() ; LineData ld; while(e.hasMoreElements()) { ld = ((LineData) e.nextElement()) ; if((y >= ld.minY) && (y <= ld.maxY)) { int x = event.getPoint().x ; if((x >= ld.minX) && (x <= ld.maxX)) { ld.data.mouseClicked(panel_, new Point(x,y), new Point(x-ld.minX,y-ld.minY)) ; } else { break ; } ; theDataManager_.prePaint() ; paint(getGraphics()) ; break ; } } } ; /** * Change manager object */ public void setManager(DataManager dataManager) { theDataManager_ = dataManager ; paint(getGraphics()) ; } /** * Called when Scrollbar object modified by user */ public void adjustmentValueChanged(AdjustmentEvent e) { firstLineNo_ = vadj_.getValue() ; paint(getGraphics()) ; } ; /** * re-paint window */ public void paint(Graphics graphics) { // Create a temp graphic object final Dimension dim = panel_.getSize() ; panel_.offScreenImage = createImage(dim.width,dim.height) ; Graphics tmpGraphics = panel_.offScreenImage.getGraphics() ; // Clear object tmpGraphics.setColor(theDataManager_.getBackground()); tmpGraphics.fillRect(0,0,dim.width,dim.height) ; // Compute lines displayed final int visibleLines = dim.height/theDataManager_.getLineHeight() ; // Adjust first line if neccesary final int totLines = theDataManager_.getLines() ; if(firstLineNo_ > totLines-visibleLines) { firstLineNo_ = totLines-visibleLines ; if(firstLineNo_ < 0) firstLineNo_ = 0 ; } // Adjust vertical scrollbar values vadj_.setMinimum(0) ; vadj_.setBlockIncrement(visibleLines) ; vadj_.setVisibleAmount(visibleLines) ; if((totLines-visibleLines)+1 > 0) { vadj_.setMaximum(totLines) ; } else vadj_.setMaximum(1) ; vadj_.setValue(firstLineNo_) ; // Clear displayed-line to data vector lineDataV_.removeAllElements() ; // Draw lines try { int line = 0 ; Vector pointByLevel = new Vector() ; int ypos = theDataManager_.getLineHeight() ; int lastLevel = 0 ; for(line = 0; (line <= visibleLines) && (line+firstLineNo_ < totLines); line++) { LineData ld = new LineData() ; ld.data = theDataManager_.getItemAt(line+firstLineNo_) ; ld.minY = ypos - theDataManager_.getLineHeight() ; ld.maxY = ypos ; final int lineBot = ypos - (theDataManager_.getLineHeight()*2)/3 ; tmpGraphics.setColor(new Color(0x40,0x40,0xff)) ; // int i ; int xp=0 ; if(ld.data.level() > 0) { if(pointByLevel.size() < ld.data.level()) { pointByLevel.setSize(ld.data.level()+1) ; for(int i=0;i< ld.data.level();i++) { final int x = ((i*theDataManager_.indentValue()) + theDataManager_.indentValue()/2) ; pointByLevel.setElementAt(new Point(x,0),i) ; } } Point p = ((Point) pointByLevel.elementAt(ld.data.level()-1)) ; tmpGraphics.drawLine(p.x,p.y, p.x,lineBot) ; p.y = lineBot ; tmpGraphics.drawLine(p.x,p.y, p.x+theDataManager_.indentValue()/2, p.y+(theDataManager_.getLineHeight()/4)) ; } Point startp = new Point(3+(ld.data.level())* theDataManager_.indentValue(), ypos) ; if(pointByLevel.size() < ld.data.level()+1) pointByLevel.setSize(ld.data.level()+1) ; pointByLevel.setElementAt(new Point(startp.x - 3 + (theDataManager_.indentValue()/2), startp.y), ld.data.level()) ; ld.minX = startp.x ; ld.maxX = (startp.x + ld.data.draw(theDataManager_.getLineHeight(), startp, tmpGraphics)) ; lineDataV_.addElement(ld) ; ypos += theDataManager_.getLineHeight() ; lastLevel = ld.data.level() ; } line += firstLineNo_ ; for(;lastLevel > 1 && line<theDataManager_.getLines();line++) { Data data = theDataManager_.getItemAt(line) ; if(data.level() < lastLevel) { lastLevel = data.level() ; } if(lastLevel > 0 && data.level() == lastLevel) { Point p = ((Point) pointByLevel.elementAt(lastLevel-1)) ; tmpGraphics.setColor(new Color(0x40,0x40,0xff)) ; tmpGraphics.drawLine(p.x,p.y, p.x,dim.height) ; } } } catch(Throwable e) { System.err.println("paint() throws:" + e) ; e.printStackTrace() ; tmpGraphics.setColor(Color.red) ; tmpGraphics.drawString(e.getMessage(),10,10) ; } panel_.paint(panel_.getGraphics()) ; } } ;
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 5093 | Hari Krishna Dara |
Populating perforce branch. I will be adding p4admin files to it. |
||
//guest/perforce_software/utils/p4db/P4DB_2.01/p4jdb/TreeDisplay.java | |||||
#1 | 1884 | rmg | Update to the current (2.01) P4DB. |