File Source: SnappingJSplitPane.java

         /* 
    P/P   *  Method: com.dmdirc.addons.ui_swing.components.SnappingJSplitPane__static_init
          */
     1  /*
     2   * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
     3   * 
     4   * Permission is hereby granted, free of charge, to any person obtaining a copy
     5   * of this software and associated documentation files (the "Software"), to deal
     6   * in the Software without restriction, including without limitation the rights
     7   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   * copies of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   * 
    11   * The above copyright notice and this permission notice shall be included in
    12   * all copies or substantial portions of the Software.
    13   * 
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   * SOFTWARE.
    21   */
    22  
    23  package com.dmdirc.addons.ui_swing.components;
    24  
    25  import com.dmdirc.config.ConfigManager;
    26  import com.dmdirc.config.IdentityManager;
    27  import com.dmdirc.interfaces.ConfigChangeListener;
    28  import com.dmdirc.addons.ui_swing.UIUtilities;
    29  
    30  import java.awt.Component;
    31  
    32  import javax.swing.JSplitPane;
    33  
    34  
    35  /**
    36   * JSplit pane that snaps around its components preferred size.
    37   */
         /* 
    P/P   *  Method: bool access$000(SnappingJSplitPane)
          * 
          *  Preconditions:
          *    x0 != null
          *    init'ed(x0.useOneTouchExpandable)
          * 
          *  Postconditions:
          *    return_value == x0.useOneTouchExpandable
          *    init'ed(return_value)
          */
    38  public class SnappingJSplitPane extends JSplitPane implements ConfigChangeListener {
    39  
    40      /**
    41       * A version number for this class. It should be changed whenever the class
    42       * structure is changed (or anything else that would prevent serialized
    43       * objects being unserialized with the new class).
    44       */
    45      private static final long serialVersionUID = 2;
    46      /** Snap distance. */
    47      private final int snapDistance;
    48      /** Component to snap to? */
    49      private boolean leftComponentSnap = true;
    50      /** use one touch expandable? */
    51      private boolean useOneTouchExpandable;
    52      /** Global config manager. */
    53      private ConfigManager config;
    54  
    55      /** Orientation type . */
             /* 
    P/P       *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane$Orientation(String, int)
              */
    56      public enum Orientation {
    57  
    58          /** Horizontal orientation. */
                 /* 
    P/P           *  Method: com.dmdirc.addons.ui_swing.components.SnappingJSplitPane$Orientation__static_init
                  * 
                  *  Postconditions:
                  *    $VALUES == &new SnappingJSplitPane$Orientation[](SnappingJSplitPane$Orientation__static_init#3)
                  *    HORIZONTAL == &new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#1)
                  *    $VALUES[0] == &new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#1)
                  *    VERTICAL == &new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#2)
                  *    $VALUES[1] == &new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#2)
                  *    new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#1) num objects == 1
                  *    new SnappingJSplitPane$Orientation(SnappingJSplitPane$Orientation__static_init#2) num objects == 1
                  *    new SnappingJSplitPane$Orientation[](SnappingJSplitPane$Orientation__static_init#3) num objects == 1
                  *    $VALUES.length == 2
                  */
    59          HORIZONTAL,
    60          /** Vertical orientation. */
    61          VERTICAL
    62      }
    63  
    64      /**
    65       * Instantiates a new snapping split pane. Defaults to using a horizontal 
    66       * split, two null components and snapping to the left component.
    67       */
    68      public SnappingJSplitPane() {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane()
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
    69          this(Orientation.HORIZONTAL);
    70      }
    71  
    72      /**
    73       * Instantiates a new snapping split pane. Defaults to using a horizontal 
    74       * split, two null components and snapping to the left component.
    75       * 
    76       * @param snapDistance Distance to around the preferred size
    77       */
    78      public SnappingJSplitPane(final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(int)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
    79          this(Orientation.HORIZONTAL, snapDistance);
    80      }
    81  
    82      /**
    83       * Instantiates a new snapping split pane. Defaults to using a horizontal 
    84       * split and two null components.
    85       * 
    86       * @param leftComponentSnap Snap to the preferred size of the left component?
    87       */
    88      public SnappingJSplitPane(final boolean leftComponentSnap) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(bool)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
    89          this(Orientation.HORIZONTAL, leftComponentSnap, 10);
    90      }
    91  
    92      /**
    93       * Instantiates a new snapping split pane. Defaults to using a horizontal 
    94       * split and two null components.
    95       * 
    96       * @param leftComponentSnap Snap to the preferred size of the left component?
    97       * @param snapDistance Distance to around the preferred size
    98       */
    99      public SnappingJSplitPane(final boolean leftComponentSnap,
   100              final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(bool, int)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
   101          this(Orientation.HORIZONTAL, leftComponentSnap, snapDistance);
   102      }
   103  
   104      /**
   105       * Instantiates a new snapping split pane. Defaults to using two null 
   106       * components and snapping to the left component.
   107       * 
   108       * @param orientation Split pane orientation 
   109       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   110       * <code>JSplitPane.VERTICAL_SPLIT</code>
   111       */
   112      public SnappingJSplitPane(final Orientation orientation) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
   113          this(orientation, null, null, 10);
   114      }
   115  
   116      /**
   117       * Instantiates a new snapping split pane. Defaults to using two null 
   118       * components and snapping to the left component.
   119       * 
   120       * @param orientation Split pane orientation 
   121       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   122       * <code>JSplitPane.VERTICAL_SPLIT</code>
   123       * @param snapDistance Distance to around the preferred size
   124       */
   125      public SnappingJSplitPane(final Orientation orientation,
   126              final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, int)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
   127          this(orientation, null, null, snapDistance);
   128      }
   129  
   130      /**
   131       * Instantiates a new snapping split pane. Defaults to using two null 
   132       * components.
   133       * 
   134       * @param orientation Split pane orientation 
   135       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   136       * <code>JSplitPane.VERTICAL_SPLIT</code>
   137       * @param leftComponentSnap Snap to the preferred size of the left component?
   138       */
   139      public SnappingJSplitPane(final Orientation orientation,
   140              final boolean leftComponentSnap) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, bool)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
   141          this(orientation, null, null, leftComponentSnap, 10);
   142      }
   143  
   144      /**
   145       * Instantiates a new snapping split pane. Defaults to using two null 
   146       * components.
   147       * 
   148       * @param orientation Split pane orientation 
   149       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   150       * <code>JSplitPane.VERTICAL_SPLIT</code>
   151       * @param leftComponentSnap Snap to the preferred size of the left component?
   152       * @param snapDistance Distance to around the preferred size
   153       */
   154      public SnappingJSplitPane(final Orientation orientation,
   155              final boolean leftComponentSnap, final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, bool, int)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
   156          this(orientation, null, null, leftComponentSnap, snapDistance);
   157      }
   158  
   159      /**
   160       * Instantiates a new snapping split pane. Defaults to using two null 
   161       * components and snapping to the left component.
   162       * 
   163       * @param orientation Split pane orientation 
   164       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   165       * <code>JSplitPane.VERTICAL_SPLIT</code>
   166       * @param leftComponent left component
   167       * @param rightComponent right component
   168       */
   169      public SnappingJSplitPane(final Orientation orientation,
   170              final Component leftComponent, final Component rightComponent) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, Component, Component)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
   171          this(orientation, leftComponent, rightComponent, true, 10);
   172      }
   173  
   174      /**
   175       * Instantiates a new snapping split pane. Defaults to using two null 
   176       * components and snapping to the left component.
   177       * 
   178       * @param orientation Split pane orientation 
   179       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   180       * <code>JSplitPane.VERTICAL_SPLIT</code>
   181       * @param leftComponent left component
   182       * @param rightComponent right component
   183       * @param snapDistance Distance to around the preferred size
   184       */
   185      public SnappingJSplitPane(final Orientation orientation,
   186              final Component leftComponent, final Component rightComponent,
   187              final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, Component, Component, int)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == 1
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
   188          this(orientation, leftComponent, rightComponent, true, snapDistance);
   189      }
   190  
   191      /**
   192       * Instantiates a new snapping split pane. Defaults to using two null 
   193       * components.
   194       * 
   195       * @param orientation Split pane orientation 
   196       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   197       * <code>JSplitPane.VERTICAL_SPLIT</code>
   198       * @param leftComponent left component
   199       * @param rightComponent right component
   200       * @param leftComponentSnap Snap to the preferred size of the left component?
   201       */
   202      public SnappingJSplitPane(final Orientation orientation,
   203              final Component leftComponent, final Component rightComponent,
   204              final boolean leftComponentSnap) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, Component, Component, bool)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == 10
                  *    init'ed(this.useOneTouchExpandable)
                  */
   205          this(orientation, leftComponent, rightComponent, leftComponentSnap, 10);
   206      }
   207  
   208      /**
   209       * Instantiates a new snapping split pane. Defaults to using two null 
   210       * components.
   211       * 
   212       * @param orientation Split pane orientation 
   213       * <code>JSplitPane.HORIZONTAL_SPLIT</code> or 
   214       * <code>JSplitPane.VERTICAL_SPLIT</code>
   215       * @param leftComponent left component
   216       * @param rightComponent right component
   217       * @param leftComponentSnap Snap to the preferred size of the left component?
   218       * @param snapDistance Distance to around the preferred size
   219       */
   220      public SnappingJSplitPane(final Orientation orientation,
   221              final Component leftComponent, final Component rightComponent,
   222              final boolean leftComponentSnap, final int snapDistance) {
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane(SnappingJSplitPane$Orientation, Component, Component, bool, int)
                  * 
                  *  Preconditions:
                  *    orientation != null
                  * 
                  *  Presumptions:
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getActionMap(...)@235 != null
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getActionMap(...)@236 != null
                  *    com.dmdirc.config.IdentityManager:getGlobalConfig(...)@229 != null
                  * 
                  *  Postconditions:
                  *    this.config != null
                  *    this.leftComponentSnap == leftComponentSnap
                  *    init'ed(this.leftComponentSnap)
                  *    this.snapDistance == snapDistance
                  *    init'ed(this.snapDistance)
                  *    init'ed(this.useOneTouchExpandable)
                  */
   223          super((orientation.equals(Orientation.HORIZONTAL)) ? HORIZONTAL_SPLIT : VERTICAL_SPLIT,
   224                  true, leftComponent, rightComponent);
   225  
   226          this.leftComponentSnap = leftComponentSnap;
   227          this.snapDistance = snapDistance;
   228  
   229          config = IdentityManager.getGlobalConfig();
   230          useOneTouchExpandable = config.getOptionBool("ui", "useOneTouchExpandable");
   231  
   232          setOneTouchExpandable(useOneTouchExpandable);
   233          setContinuousLayout(true);
   234          
   235          getActionMap().setParent(null);
   236          getActionMap().clear();
   237  
   238          config.addChangeListener("ui", "useOneTouchExpandable", this);
   239      }
   240  
   241      /** {@inheritDoc} */
   242      @Override
   243      public void setDividerLocation(final int location) {
                 /* 
    P/P           *  Method: void setDividerLocation(int)
                  * 
                  *  Preconditions:
                  *    init'ed(this.leftComponentSnap)
                  * 
                  *  Test Vectors:
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getOrientation(...)@244: {-231..0, 2..232-1}, {1}
                  */
   244          if (getOrientation() == HORIZONTAL_SPLIT) {
   245              setDividerLocationHorizontal(location);
   246          } else {
   247              setDividerLocationVertical(location);
   248          }
   249      }
   250  
   251      /**
   252       * Sets the divider location snapping to the preferred component size.
   253       * 
   254       * @param location new location
   255       */
   256      private void setDividerLocationHorizontal(final int location) {
                 /* 
    P/P           *  Method: void setDividerLocationHorizontal(int)
                  * 
                  *  Preconditions:
                  *    init'ed(this.leftComponentSnap)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getLeftComponent(...)@258 != null
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getRightComponent(...)@262 != null
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getWidth(...)@263 - location in {-232..6_442_450_943}
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getWidth(...)@265 - java.awt.Component:getPreferredSize(...).width@262 in {-231..232-1}
                  *    java.awt.Component:getPreferredSize(...).width@258 - location in {-231..232-1}
                  *    ...
                  * 
                  *  Test Vectors:
                  *    this.leftComponentSnap: {0}, {1}
                  */
   257          if (leftComponentSnap) {
   258              final int pref = getLeftComponent().getPreferredSize().width;
   259              super.setDividerLocation(Math.abs(pref - location) <= snapDistance ? pref
   260                      : location);
   261          } else {
   262              final int pref = getRightComponent().getPreferredSize().width;
   263              final int result = Math.abs(getWidth() - location - pref);
   264              if (result >= -snapDistance && result <= snapDistance) {
   265                  super.setDividerLocation(Math.abs(getWidth() - pref));
   266              } else {
   267                  super.setDividerLocation(location);
   268              }
   269          }
   270      }
   271  
   272      /**
   273       * Sets the divider location snapping to the preferred component size.
   274       * 
   275       * @param location new location
   276       */
   277      private void setDividerLocationVertical(final int location) {
                 /* 
    P/P           *  Method: void setDividerLocationVertical(int)
                  * 
                  *  Preconditions:
                  *    init'ed(this.leftComponentSnap)
                  * 
                  *  Presumptions:
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getLeftComponent(...)@279 != null
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getRightComponent(...)@283 != null
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getWidth(...)@284 - location in {-232..6_442_450_943}
                  *    com.dmdirc.addons.ui_swing.components.SnappingJSplitPane:getWidth(...)@286 - java.awt.Component:getPreferredSize(...).height@283 in {-231..232-1}
                  *    java.awt.Component:getPreferredSize(...).height@279 - location in {-231..232-1}
                  *    ...
                  * 
                  *  Test Vectors:
                  *    this.leftComponentSnap: {0}, {1}
                  */
   278          if (leftComponentSnap) {
   279              final int pref = getLeftComponent().getPreferredSize().height;
   280              super.setDividerLocation(Math.abs(pref - location) <= snapDistance ? pref
   281                      : location);
   282          } else {
   283              final int pref = getRightComponent().getPreferredSize().height;
   284              final int result = Math.abs(getWidth() - location - pref);
   285              if (result >= -snapDistance && result <= snapDistance) {
   286                  super.setDividerLocation(Math.abs(getWidth() - pref));
   287              } else {
   288                  super.setDividerLocation(location);
   289              }
   290          }
   291      }
   292  
   293      /** {@inheritDoc} */
   294      @Override
   295      public void configChanged(final String domain, final String key) {
                 /* 
    P/P           *  Method: void configChanged(String, String)
                  * 
                  *  Preconditions:
                  *    this.config != null
                  * 
                  *  Postconditions:
                  *    init'ed(this.useOneTouchExpandable)
                  */
   296          useOneTouchExpandable = config.getOptionBool("ui", "useOneTouchExpandable");
   297  
                 /* 
    P/P           *  Method: void com.dmdirc.addons.ui_swing.components.SnappingJSplitPane$1(SnappingJSplitPane)
                  */
   298          UIUtilities.invokeLater(new Runnable() {
   299  
   300              /** {@inheritDoc} */
   301              @Override
   302              public void run() {
                         /* 
    P/P                   *  Method: void run()
                          * 
                          *  Preconditions:
                          *    init'ed(this.useOneTouchExpandable)
                          */
   303                  setOneTouchExpandable(useOneTouchExpandable);
   304              }
   305          });
   306      }
   307  }
   308      








SofCheck Inspector Build Version : 2.17854
SnappingJSplitPane.java 2009-Jun-25 01:54:24
SnappingJSplitPane.class 2009-Sep-02 17:04:15
SnappingJSplitPane$1.class 2009-Sep-02 17:04:15
SnappingJSplitPane$Orientation.class 2009-Sep-02 17:04:15