Outliner.java
上传用户:gyyuli
上传日期:2013-07-09
资源大小:3050k
文件大小:25k
源码类别:

J2ME

开发平台:

Java

  1. import javax.microedition.midlet.*;
  2. import javax.microedition.lcdui.*;
  3. import java.util.Vector;
  4. import java.util.Enumeration;
  5. /**
  6. * A simple outlining midlet.
  7. */ 
  8. public class Outliner extends MIDlet 
  9.     implements CommandListener, ItemCommandListener
  10.     private static Display DISPLAY;
  11.     private static Command exitCommand, editCommand, insertCommand, 
  12.         indentCommand, outdentCommand, expandCommand, collapseCommand,
  13.         deleteCommand, okCommand, cancelCommand, upCommand, downCommand;
  14.     private Form form;
  15.     private TextBox textBox;
  16.     private OutlineItem editedItem;
  17.     
  18.     // user-visible strings
  19.     private final static String EXIT = "Exit";
  20.     private final static String EDIT = "Edit";
  21.     private final static String UP = "Move Up";
  22.     private final static String DOWN = "Move Down";
  23.     private final static String INDENT = "Indent";
  24.     private final static String OUTDENT = "Outdent";
  25.     private final static String EXPAND = "Expand";
  26.     private final static String COLLAPSE = "Collapse";
  27.     private final static String INSERT = "Insert";
  28.     private final static String DELETE = "Delete";
  29.     private final static String OK = "OK";
  30.     private final static String CANCEL = "Cancel";
  31.     // font for rendering items
  32.     public static Font FONT = Font.getFont( Font.FONT_STATIC_TEXT );
  33.     public static int FONT_HEIGHT = Math.max( FONT.getHeight(), 9 );
  34.     
  35.     public Outliner()
  36.     {
  37.         DISPLAY = null;
  38.         editedItem = null;
  39.     
  40.         exitCommand = new Command( EXIT, Command.EXIT, 0 );
  41.         okCommand = new Command( OK, Command.OK, 1 );
  42.         cancelCommand = new Command( CANCEL, Command.CANCEL, 2 );
  43.         editCommand = new Command( EDIT, Command.ITEM, 1 );
  44.         insertCommand = new Command( INSERT, Command.ITEM, 2 );
  45.         indentCommand = new Command( INDENT, Command.ITEM, 3 );
  46.         outdentCommand = new Command( OUTDENT, Command.ITEM, 4 );
  47.         upCommand = new Command( UP, Command.ITEM, 5 );
  48.         downCommand = new Command( DOWN, Command.ITEM, 6 );
  49.         expandCommand = new Command( EXPAND, Command.ITEM, 7 );
  50.         collapseCommand = new Command( COLLAPSE, Command.ITEM, 8 );
  51.         deleteCommand = new Command( DELETE, Command.ITEM, 9 );
  52.         
  53.         // set up outline form
  54.         form = new Form( "CustomItem 演示" );
  55.         form.addCommand( exitCommand );
  56.         form.setCommandListener( this );
  57.         
  58.         // setup input form
  59.         textBox = new TextBox( null, "", 255, TextField.ANY );
  60.         textBox.addCommand( okCommand );
  61.         textBox.addCommand( cancelCommand );
  62.         textBox.setCommandListener( this );
  63.         
  64.         OutlineItem item;
  65.         item = new OutlineItem( 0, "This is an outline" );
  66.         item.setItemCommandListener( this );
  67.         item.appendToForm( form );
  68.         item = new OutlineItem( 1, "This is a nested item" );
  69.         item.setItemCommandListener( this );
  70.         item.appendToForm( form );
  71.         item = new OutlineItem( 2, "This is a double-nested item" );
  72.         item.setItemCommandListener( this );
  73.         item.appendToForm( form );
  74.         item = new OutlineItem( 1, "This is another nested item" );
  75.         item.setItemCommandListener( this );
  76.         item.appendToForm( form );
  77.     }
  78.     public void startApp()
  79.     {
  80.         if ( DISPLAY == null )
  81.         {
  82.             DISPLAY = Display.getDisplay( this );
  83.             DISPLAY.setCurrent( form );
  84.         }
  85.     }
  86.     public void pauseApp()
  87.     {
  88.     }
  89.     
  90.     public void destroyApp( boolean unconditional )
  91.     {
  92.     }
  93.         
  94.     public void onShowInput()
  95.     {
  96.         if ( editedItem != null )
  97.         {
  98.             textBox.setString( editedItem.getString() );
  99.         }
  100.         DISPLAY.setCurrent( textBox );
  101.     }
  102.     
  103.     public void onDoInput()
  104.     {
  105.         if ( editedItem != null )
  106.         {
  107.             editedItem.setString( textBox.getString() );
  108.             editedItem = null;
  109.         }
  110.     }   
  111.     
  112.     public void onHideInput()
  113.     {
  114.         DISPLAY.setCurrent( form );
  115.         textBox.setString( "" ); // clear last command if any
  116.         editedItem = null;
  117.     }
  118.     
  119.     // interface CommandListener
  120.     
  121.     public void commandAction( Command aCommand, Displayable aDisplayable )
  122.     {
  123.         if ( aCommand == exitCommand )
  124.         {
  125.             destroyApp( true );
  126.             notifyDestroyed();
  127.         }
  128.         else
  129.         if ( aCommand == okCommand )
  130.         {
  131.             onDoInput();
  132.             onHideInput();
  133.         }
  134.         else
  135.         if ( aCommand == cancelCommand )
  136.         {
  137.             onHideInput();
  138.         }
  139.     }
  140.     
  141.     // interface ItemCommandListener
  142.     
  143.     public void commandAction( Command aCommand, Item anItem )
  144.     {
  145.         OutlineItem item = (OutlineItem) anItem;
  146.         
  147.         if ( aCommand == expandCommand )
  148.         {
  149.             item.expand();
  150.         }
  151.         else
  152.         if ( aCommand == collapseCommand )
  153.         {
  154.             item.collapse();
  155.         }
  156.         else
  157.         if ( aCommand == indentCommand )
  158.         {
  159.             item.indent();
  160.         }
  161.         else
  162.         if ( aCommand == outdentCommand )
  163.         {
  164.             item.outdent();
  165.         }
  166.         else
  167.         if ( aCommand == upCommand )
  168.         {
  169.             item.moveUp();
  170.         }
  171.         else
  172.         if ( aCommand == downCommand )
  173.         {
  174.             item.moveDown();
  175.         }
  176.         else
  177.         if ( aCommand == editCommand )
  178.         {
  179.             editedItem = item;
  180.             onShowInput();
  181.         }
  182.         else
  183.         if ( aCommand == insertCommand )
  184.         {
  185.             OutlineItem newItem = new OutlineItem( 
  186.                 item.indent, "" );
  187.             newItem.setItemCommandListener( this );
  188.             newItem.insertAfterItem( form, item );
  189.         }
  190.         else
  191.         if ( aCommand == deleteCommand )
  192.         {
  193.             item.removeFromForm();
  194.         }
  195.     }
  196.     
  197.         public static class OutlineItem extends CustomItem
  198.         {
  199.         /**
  200.         * The number of pixels to shift for each level of indent.
  201.         */ 
  202.         private static final int INDENT_MARGIN = 8;
  203.         /**
  204.         * The number of levels to indent.
  205.         */ 
  206.         private int indent;
  207.         /**
  208.         * The text to display when painted.
  209.         */
  210.         private String text;
  211.         /**
  212.         * The parent form of this item.  Needed to 
  213.         * perform expand and collapse operations.
  214.         */
  215.         private Form parentForm;
  216.         /**
  217.         * A list of OutlineItems that are collapsed under this one.
  218.         * If this item is expanded, this vector is null.
  219.         */
  220.         private Vector children;
  221.         /**
  222.         * The traversing item.
  223.         */ 
  224.         private static OutlineItem traversingItem;
  225.         /**
  226.         * Creates an OutlineItem with the specified initial indent and text.
  227.         */
  228.         public OutlineItem( int inIndent, String inText )
  229.         {
  230.             // we don't want a system-supplied label
  231.             super( null );
  232.             
  233.             indent = inIndent;
  234.             text = inText;
  235.             children = null;
  236.             // define layout constraitns
  237.             setLayout( LAYOUT_2 | LAYOUT_LEFT | LAYOUT_TOP |
  238.                 LAYOUT_EXPAND | LAYOUT_NEWLINE_AFTER );
  239.             // add the commands that always apply
  240.             addCommand( editCommand );
  241.             addCommand( insertCommand );
  242.         }
  243.         /**
  244.         * Returns the indent for this item.
  245.         */
  246.         public int getIndent()
  247.         {
  248.             return indent;
  249.         }
  250.         
  251.         /**
  252.         * Sets the indent for this item.
  253.         */
  254.         public void setIndent( int inIndent )
  255.         {
  256.             indent = inIndent;
  257.             updateCommands();
  258.         }
  259.         
  260.         /**
  261.         * Returns the text for this item.
  262.         */
  263.         public String getString()
  264.         {
  265.             return text;
  266.         }
  267.         
  268.         /**
  269.         * Sets the text for this item.
  270.         */
  271.         public void setString( String inText )
  272.         {
  273.             text = inText;
  274.             invalidate();
  275.         }
  276.         
  277.         /**
  278.         * Add this item to the end of the form.
  279.         */
  280.         public void appendToForm( Form inForm )
  281.         {
  282.             insertBeforeItem( inForm, null );
  283.         }
  284.         
  285.         /**
  286.         * Add this item to the form before the specified item.
  287.         */
  288.         public void insertBeforeItem( Form inForm, OutlineItem inItem )
  289.         {
  290.             if ( parentForm != null )
  291.             {
  292.                 removeFromForm();
  293.             }
  294.             parentForm = inForm;
  295.         
  296.             int i;
  297.             int size = parentForm.size();
  298.             for ( i = 0; i < size; i++ )
  299.             {
  300.                 if ( parentForm.get( i ) == inItem )
  301.                 {
  302.                     break;
  303.                 }
  304.             }
  305.             parentForm.insert( i, this );
  306.             if ( inItem != null ) inItem.updateCommands();
  307.             updateCommands();
  308.         }
  309.         
  310.         /**
  311.         * Add this item to the form before the specified item.
  312.         */
  313.         public void insertAfterItem( Form inForm, OutlineItem inItem )
  314.         {
  315.             if ( parentForm != null )
  316.             {
  317.                 removeFromForm();
  318.             }
  319.             parentForm = inForm;
  320.         
  321.             int i;
  322.             int size = parentForm.size();
  323.             for ( i = 0; i < size; i++ )
  324.             {
  325.                 if ( parentForm.get( i ) == inItem )
  326.                 {
  327.                     break;
  328.                 }
  329.             }
  330.             parentForm.insert( i+1, this );
  331.             if ( inItem != null ) inItem.updateCommands();
  332.             updateCommands();
  333.         }
  334.         
  335.         /**
  336.         * Remove this item from the form.
  337.         */
  338.         public void removeFromForm()
  339.         {
  340.             int size = parentForm.size();
  341.             for ( int i = 0; i < size; i++ )
  342.             {
  343.                 if ( parentForm.get( i ) == this )
  344.                 {
  345.                     parentForm.delete( i ); // delete this
  346.                     break;
  347.                 }
  348.             }
  349.         }
  350.         
  351.         /**
  352.         * Returns the index of this item on the form.
  353.         * Returns -1 if the item is not on the form.
  354.         */
  355.         public int getIndex()
  356.         {
  357.             if ( parentForm != null )
  358.             {
  359.                 int size = parentForm.size();
  360.                 for ( int i = 0; i < size; i++ )
  361.                 {
  362.                     if ( parentForm.get( i ) == this )
  363.                     {
  364.                         return i;
  365.                     }
  366.                 }
  367.             }
  368.             return -1;
  369.         }
  370.         
  371.         /**
  372.         * Returns whether this item can be indented further.
  373.         */
  374.         public boolean isIndentable()
  375.         {
  376.             int index = getIndex();
  377.             // root cannot be indented
  378.             if ( index == 0 ) return false;
  379.             OutlineItem parent = (OutlineItem)parentForm.get( index - 1 );
  380.             if ( this.indent < parent.indent ) return true;
  381.             return ( !parent.isCollapsed() && this.indent <= parent.indent);
  382.         }
  383.         
  384.         /**
  385.         * Indent the specified node by one unit.
  386.         */
  387.         public void indent()
  388.         {
  389.             indentChildren();
  390.             setIndent( indent+1 );
  391.         }
  392.         
  393.         private void indentChildren()
  394.         {
  395.             if ( isCollapsed() )
  396.             {
  397.                 Enumeration e = getHiddenChildren().elements();
  398.                 while ( e.hasMoreElements() )
  399.                 {
  400.                     ((OutlineItem)e.nextElement()).indent++;
  401.                 }
  402.             }
  403.             else
  404.             {   
  405.                 OutlineItem item;
  406.                 for ( int index = getIndex() + 1; index < parentForm.size(); index++ )
  407.                 {
  408.                     item = (OutlineItem) parentForm.get( index );
  409.                     if ( item.getIndent() > getIndent() ) // our indent hasn't changed yet
  410.                     {
  411.                         item.indent++;
  412.                     }
  413.                     else // end of children
  414.                     {
  415.                         break;
  416.                     }
  417.                 }
  418.             }
  419.         }
  420.         
  421.         /**
  422.         * Returns whether this item can be outdented further.
  423.         */
  424.         public boolean isOutdentable()
  425.         {
  426.             return ( indent > 0 );
  427.         }
  428.         
  429.         /**
  430.         * Outdent the specified node by one unit.
  431.         */
  432.         public void outdent()
  433.         {
  434.             outdentChildren();
  435.             setIndent( indent-1 );
  436.         }
  437.         
  438.         private void outdentChildren()
  439.         {
  440.             if ( isCollapsed() )
  441.             {
  442.                 Enumeration e = getHiddenChildren().elements();
  443.                 while ( e.hasMoreElements() )
  444.                 {
  445.                     ((OutlineItem)e.nextElement()).indent--;
  446.                 }
  447.             }
  448.             else
  449.             {   
  450.                 OutlineItem item;
  451.                 for ( int index = getIndex() + 1; index < parentForm.size(); index++ )
  452.                 {
  453.                     item = (OutlineItem) parentForm.get( index );
  454.                     if ( item.getIndent() > getIndent() ) // our indent hasn't changed yet
  455.                     {
  456.                         item.indent--;
  457.                     }
  458.                     else // end of children
  459.                     {
  460.                         break;
  461.                     }
  462.                 }
  463.             }
  464.         }
  465.         
  466.         /**
  467.         * Returns whether this item can be moved up.
  468.         */
  469.         public boolean canMoveUp()
  470.         {
  471.             if ( parentForm == null ) return false;
  472.             OutlineItem item;
  473.             int index = getIndex();
  474.             for ( int i = getIndex(); i > 0; i = i-1 )
  475.             {
  476.                 item = (OutlineItem) parentForm.get( i );
  477.                 if ( item.indent == this.indent )
  478.                 {
  479.                     return true;
  480.                 }
  481.                 if ( item.indent < this.indent )
  482.                 {
  483.                     return false;
  484.                 }
  485.             }
  486.             return false;
  487.         }
  488.         
  489.         /**
  490.         * Outdent the specified node by one unit.
  491.         */
  492.         public void moveUp()
  493.         {
  494.             OutlineItem item;
  495.             for ( int i = getIndex()-1; i > 0; i = i-1 )
  496.             {
  497.                 item = (OutlineItem) parentForm.get( i );
  498.                 if ( item.indent == this.indent )
  499.                 {
  500.                     // collapse children before moving node
  501.                     Form f = this.parentForm;
  502.                     boolean collapsed = this.isCollapsed();
  503.                     if ( !collapsed ) this.collapse();
  504.                     this.removeFromForm();
  505.                     this.insertBeforeItem( f, item );
  506.                     if ( !collapsed ) this.expand();
  507.                     break;
  508.                 }
  509.                 if ( item.indent < this.indent )
  510.                 {
  511.                     break;
  512.                 }
  513.             }
  514.             updateCommands();
  515.         }
  516.         
  517.         /**
  518.         * Returns whether this item can be moved down.
  519.         */
  520.         public boolean canMoveDown()
  521.         {
  522.             if ( parentForm == null ) return false;
  523.             OutlineItem item;
  524.             int size = parentForm.size();
  525.             for ( int i = getIndex(); i < size-1; i = i+1 )
  526.             {
  527.                 item = (OutlineItem) parentForm.get( i );
  528.                 if ( item.indent == this.indent )
  529.                 {
  530.                     return true;
  531.                 }
  532.                 if ( item.indent < this.indent )
  533.                 {
  534.                     return false;
  535.                 }
  536.             }
  537.             return false;
  538.         }
  539.         
  540.         /**
  541.         * Outdent the specified node by one unit.
  542.         */
  543.         public void moveDown()
  544.         {
  545.             OutlineItem item;
  546.             int size = parentForm.size();
  547.             for ( int i = getIndex(); i < size; i = i+1 )
  548.             {
  549.                 item = (OutlineItem) parentForm.get( i );
  550.                 if ( item.indent == this.indent )
  551.                 {
  552.                     i = i+1;
  553.                     Form f = this.parentForm;
  554.                     boolean collapsed = this.isCollapsed();
  555.                     if ( !collapsed ) this.collapse();
  556.                     if ( i > size ) 
  557.                     {
  558.                         this.removeFromForm();
  559.                         this.appendToForm( f );
  560.                     }
  561.                     else
  562.                     {
  563.                         // collapse children before moving node
  564.                         item = (OutlineItem) parentForm.get( i );
  565.                         this.removeFromForm();
  566.                         boolean targetCollapsed = item.isCollapsed();
  567.                         if ( !targetCollapsed ) item.collapse();
  568.                         this.insertAfterItem( f, item );
  569.                         if ( !targetCollapsed ) item.expand();
  570.                     }
  571.                     if ( !collapsed ) this.expand();
  572.                     break;
  573.                 }
  574.             }
  575.             updateCommands();
  576.         }
  577.         
  578.         /**
  579.         * Returns whether this item has hidden children.
  580.         */
  581.         public boolean isCollapsed()
  582.         {
  583.             return ( children != null );
  584.         }
  585.         
  586.         /**
  587.         * Hide all subsequent items with greater indent
  588.         * and add them to the hidden children list.
  589.         */
  590.         public void collapse()
  591.         {
  592.             if ( children != null ) return;
  593.             Vector hidden = new Vector();
  594.             for ( int i = 0; i < parentForm.size(); i++ )
  595.             {
  596.                 if ( parentForm.get( i ) == this )
  597.                 {
  598.                     OutlineItem item;
  599.                     i = i + 1;
  600.                     while ( i < parentForm.size() )
  601.                     {
  602.                         item = (OutlineItem)parentForm.get( i );
  603.                         if ( item.indent > this.indent )
  604.                         {
  605.                             parentForm.delete( i ); // delete item
  606.                             hidden.addElement( item );
  607.                         }
  608.                         else
  609.                         {
  610.                             break;
  611.                         }
  612.                     }
  613.                     break;
  614.                 }
  615.             }
  616.             if ( hidden.size() > 0 )
  617.             { 
  618.                 setHiddenChildren( hidden );
  619.                 updateCommands();
  620.             }
  621.         }
  622.         
  623.         /**
  624.         * Show this nodes hidden children, if any.
  625.         */
  626.         public void expand()
  627.         {
  628.             if ( children == null ) return;
  629.             int i;
  630.             int size = parentForm.size();
  631.             for ( i = 0; i < size; i++ )
  632.             {
  633.                 if ( parentForm.get( i ) == this )
  634.                 {
  635.                     i = i + 1;
  636.                     break;
  637.                 }
  638.             }
  639.             OutlineItem item;
  640.             Enumeration e = children.elements();
  641.             while ( e.hasMoreElements() )
  642.             {
  643.                 item = (OutlineItem) e.nextElement();
  644.                 parentForm.insert( i, item ); // insert item
  645.                 i = i + 1;
  646.             }
  647.             setHiddenChildren( null );
  648.             updateCommands();
  649.         }
  650.         
  651.         /**
  652.         * Returns the children that are currently collapsed
  653.         * and are therefore not referenced by the parent form.
  654.         */
  655.         protected Vector getHiddenChildren()
  656.         {
  657.             return children;
  658.         }
  659.         
  660.         /**
  661.         * Set the children that are currently collapsed
  662.         * so that we retain a reference to them when they
  663.         * are removed from the form.
  664.         */
  665.         protected void setHiddenChildren( Vector inChildren )
  666.         {
  667.             children = inChildren;
  668.         }
  669.         
  670.         private boolean hasPointerPress()
  671.         {
  672.             return ( getInteractionModes() & POINTER_PRESS ) != 0;
  673.         }
  674.         
  675.         private boolean hasHorizontalTraversal()
  676.         {
  677.             return ( getInteractionModes() & TRAVERSE_HORIZONTAL ) != 0;
  678.         }
  679.         
  680.         private void updateCommands()
  681.         {
  682.             removeCommand( expandCommand );
  683.             removeCommand( collapseCommand );
  684.             if ( !hasPointerPress() )
  685.             {
  686.                 // fall back on commands to expand/collapse
  687.                 if ( isCollapsed() )
  688.                     addCommand( expandCommand );
  689.                 else
  690.                     addCommand( collapseCommand );
  691.             }
  692.             
  693.             removeCommand( indentCommand );
  694.             removeCommand( outdentCommand );
  695.             if ( !hasHorizontalTraversal() )
  696.             {
  697.                 // fall back on commands to indent/outdent
  698.                 if ( isIndentable() )
  699.                     addCommand( indentCommand );
  700.                 if ( isOutdentable() )                
  701.                     addCommand( outdentCommand );
  702.             }
  703.             
  704.             removeCommand( upCommand );
  705.             removeCommand( downCommand );
  706.             if ( canMoveUp() )
  707.                 addCommand( upCommand );
  708.             if ( canMoveDown() )                
  709.                 addCommand( downCommand );
  710.             removeCommand( deleteCommand );
  711.             if ( getIndex() > 0 )
  712.             {
  713.                 // if not root
  714.                 addCommand( deleteCommand );
  715.             }
  716.             
  717.             // force a repaint
  718.             if ( parentForm != null )
  719.             {
  720.                 invalidate();
  721.                 //repaint();
  722.             }
  723.         }
  724.         
  725.         // event handler overrides
  726.         
  727.         /**
  728.         * Overridden to grab or drop the current item
  729.         * when the FIRE key is pressed.
  730.         */
  731.         protected void keyPressed( int keyCode )
  732.         {
  733.             if ( getGameAction( keyCode ) == Canvas.FIRE )
  734.             {
  735.                 if ( isCollapsed() )
  736.                     expand();
  737.                 else
  738.                     collapse();
  739.             }
  740.         }
  741.                                        
  742.         /**
  743.         * Overridden to expand or collapse an item
  744.         * if the 'expansion widget' is clicked.
  745.         * Note that the reference implementation only
  746.         * delivers this event if the item is "focused".
  747.         */
  748.         protected void pointerPressed( int x, int y )
  749.         {
  750.             // if in widget area
  751.             if ( x < FONT_HEIGHT )
  752.             {
  753.                 if ( isCollapsed() ) 
  754.                     expand();
  755.                 else 
  756.                     collapse();
  757.             }
  758.         }
  759.         
  760.         /**
  761.         * Used to indent and outdent the item when possible.
  762.         */
  763.         protected boolean traverse( 
  764.             int dir,
  765.             int viewportWidth,
  766.             int viewportHeight,
  767.             int[] visRect_inout )
  768.         {
  769.             // this flag distinguishes between
  770.             // traversing INTO this item and
  771.             // traversing WITHIN this item:
  772.             if ( traversingItem != this )
  773.             {
  774.                 // traversing INTO: mark self and return true
  775.                 traversingItem = this;
  776.                 return true;
  777.             }
  778.             
  779.             // handle traversing WITHIN this item
  780.             switch ( dir )
  781.             {
  782.                 case Canvas.RIGHT:
  783.                     if ( isIndentable() )
  784.                     {
  785.                         indent();
  786.                     }
  787.                     return true;
  788.                 case Canvas.LEFT:
  789.                     if ( isOutdentable() )
  790.                     {
  791.                         outdent();
  792.                     }
  793.                     return true;
  794.                 case NONE:
  795.                     // do nothing: just a form layout reflow
  796.                     return true;
  797.                 default:
  798.                     // break out
  799.             }
  800.             return false;
  801.         }
  802.                                        
  803.         // implementation of abstract methods
  804.         
  805.         public int getMinContentHeight()
  806.         {
  807.             return FONT_HEIGHT;
  808.         }
  809.         public int getMinContentWidth()
  810.         {
  811.             return indent * INDENT_MARGIN + FONT_HEIGHT;
  812.             // we might not have text to calculate font width
  813.         }
  814.         public int getPrefContentWidth( int height )
  815.         {
  816.             return indent * INDENT_MARGIN 
  817.                 + FONT.stringWidth( text ) + FONT_HEIGHT;
  818.         }
  819.         public int getPrefContentHeight( int width )
  820.         {
  821.             return FONT_HEIGHT;
  822.         }
  823.         public void paint( Graphics g, int w, int h )
  824.         {
  825.             // clear all with background color
  826.             g.setColor( DISPLAY.getColor( DISPLAY.COLOR_BACKGROUND ) );
  827.             g.fillRect( 0, 0, w, h );
  828.             
  829.             // now use foreground color for drawing
  830.             g.setColor( DISPLAY.getColor( DISPLAY.COLOR_FOREGROUND ) );
  831.                         
  832.             if ( isCollapsed() )
  833.             {
  834.                 // draw a filled circle to represent hidden items
  835.                 g.fillArc( indent * INDENT_MARGIN + 2, 2, 
  836.                     FONT_HEIGHT-7, FONT_HEIGHT-7, 0, 360 );
  837.             }
  838.             else
  839.             {
  840.                 // no hidden items so draw an empty circle
  841.                 g.drawArc( indent * INDENT_MARGIN + 2, 2, 
  842.                     FONT_HEIGHT-7, FONT_HEIGHT-7, 0, 360 );
  843.             }
  844.             
  845.             // draw the text: word-wrap is an exercise for the reader
  846.             g.drawString( text, 
  847.                 indent * INDENT_MARGIN + FONT_HEIGHT, 0, g.TOP | g.LEFT );
  848.         }
  849.     }
  850.     
  851. }