Package pspdash

Source Code of pspdash.TaskTemplate

// PSP Dashboard - Data Automation Tool for PSP-like processes
// Copyright (C) 1999  United States Air Force
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// The author(s) may be contacted at:
// OO-ALC/TISHD
// Attn: PSP Dashboard Group
// 6137 Wardleigh Road
// Hill AFB, UT 84056-5843
//
// E-Mail POC:  ken.raisor@hill.af.mil


package pspdash;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.text.JTextComponent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import pspdash.data.DataRepository;
import pspdash.data.NumberData;
import pspdash.data.DateData;
import pspdash.data.DoubleData;


public class TaskTemplate extends Object implements TreeSelectionListener, TableValidator
{
  /** Class Attributes */
  protected JFrame          frame;
  protected JTree           tree;
  protected PropTreeModel   treeModel;
  protected PSPProperties   useProps;
  protected PSPDashboard    dashboard = null;
  protected ValidatingTable taskTable;
  protected ValidatingTable scheduleTable;
  protected JCheckBox       autoCalc;
  protected JComboBox       taskNames;

  protected Vector          listOfNodes = new Vector();
  protected boolean         autoCalculateOn = false;
  protected JTextField      startDate = null;
  protected String          taskFile;
  protected String          taskSheetName;
  protected Properties      taskProps = null;

  Vector currentTaskLog     = new Vector();
  Vector currentScheduleLog = new Vector();

  DataRepository data         = null;
  TimeLog        tl           = new TimeLog();
  String         validateCell = null;

  static final long   DAY_IN_MILLIS  = 24 * 60 * 60 * 1000;
  static final int    TASK_TABLE     = 0;
  static final int    SCHEDULE_TABLE = 1;
  static final int    EV_DECIMALS    = 1;

  static final String COMPLETED_TIME = "Completed";
  static final String PLANNED_TIME   = "Estimated Time";

  static final String NEW_TOKEN      = "<new>"; // pull menu options
  static final String DELETE_TOKEN   = "<delete>";
  static final String NO_SELECTION   = "<none>";

  static final String ID_SEP         = "|"; // id field divider

  static final String TAB            = "        "; // prop field divider
  static final String TASK_KEY       = "<tasks>"// top prop for task sheet
  static final String PT_START       = ".start";   // Props for task sheet
  static final String PT_EXTERNAL    = ".external";
  static final String PT_WEEKS       = ".weeks";


  //
  // member functions
  //
  private void debug(String msg) {
    System.out.println("TaskTemplate:" + msg);
  }



                                // constructor
  public TaskTemplate(PSPDashboard dash,
                      ConfigureButton button,
                      PSPProperties props) {
    dashboard    = dash;
    JPanel panel = new JPanel();

    useProps = props;
    data     = dashboard.getDataRepository();

    try {
      tl.read (dashboard.getTimeLog());
    } catch (IOException e) {}

    frame = new JFrame("TaskTemplate");
    frame.setTitle("TaskTemplate");
    frame.setBackground(Color.lightGray);

    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints g = new GridBagConstraints();
    panel.setLayout(layout);
    JPanel p;
    p = constructHeaderPanel();
    g.fill  = GridBagConstraints.HORIZONTAL;
    g.gridx = 0;
    layout.setConstraints (p, g);
    panel.add (p);
    g.fill = GridBagConstraints.BOTH;
    g.weighty = 1.0;
    g.weightx = 1.0;
    Insets dInsets = g.insets;
    g.insets = new Insets (0, 3, 0, 3);
    JSplitPane jsp = new JSplitPane (JSplitPane.VERTICAL_SPLIT,
                                     constructTaskPanel(),
                                     constructSchedulePanel());
    layout.setConstraints (jsp, g);
    panel.add (jsp);
    g.fill = GridBagConstraints.HORIZONTAL;
    g.weighty = 0.0;
    g.weightx = 0.0;
    g.insets = dInsets;
    p = constructControlPanel();
    layout.setConstraints (p, g);
    panel.add (p);

    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        frame.setVisible (false);
      }
    });

    calculate();
    frame.getContentPane().add("Center", panel);
    frame.pack();
    frame.show();

    getListOfNodes(listOfNodes, useProps);

    taskFile = Settings.getVal ("taskFile");
    taskProps = new Properties ();
    try {
      taskProps.load (new FileInputStream(taskFile));
    } catch (Exception e) {}
  }



  public void save() {
    if (taskProps != null) {
      try {
        FileOutputStream out = new FileOutputStream (taskFile);
        taskProps.store(out, "Task & Schedule Template Data");
      } catch (Exception e2) {}
    }

    Date d = DateFormatter.parseDate (startDate.getText());
    Object a;
    if (d == null)
      a = taskProps.remove (taskSheetName + PT_START);
    else
      taskProps.put (taskSheetName + PT_START, "" + d.getTime());
  }



  protected void addChildNodeNames (Vector v,
                                    PSPProperties props,
                                    PropertyKey pk) {
    v.addElement (pk.path());
    for (int ii = 0; ii < props.getNumChildren(pk); ii++) {
      addChildNodeNames (v, props, props.getChildKey(pk, ii));
    }
  }



  protected void getListOfNodes (Vector v, PSPProperties props) {
    addChildNodeNames (v, props, PropertyKey.ROOT);
  }



  protected void addTask (String s) {
    PropertyKey pk;
    String      node;
    for (int ii = 0; ii < listOfNodes.size(); ii++) {
      node = (String)listOfNodes.elementAt (ii);
      if (node.startsWith (s)) {
        pk = PropertyKey.fromPath (node);
        if (useProps.getNumChildren (pk) == 0)
          addTaskRow (pk);
        listOfNodes.removeElementAt (ii--);
      }
    }
    calculate();
  }



  public long scanTask (TaskEntry te) { // fill in 'slurp'able data fields
    String thePath = te.taskName.path();

    NumberData pt = (NumberData)data.getSimpleValue (thePath + PLANNED_TIME);
    te.plannedTime = ((pt == null) ? 0 : pt.getInteger());
    DateData ad = (DateData)data.getSimpleValue (thePath + COMPLETED_TIME);
    te.actualDate = ((ad == null) ? null : ad.getValue());
    return te.plannedTime;
  }



  protected String stringDouble (double x, int afterDot) {
    double factor = Math.pow (10.0, (double)afterDot);
    return String.valueOf (Math.round (x * factor) / factor);
  }



  protected Object [] getScheduleRow (long weekNumber,
                                      Date startDate,
                                      ScheduleEntry se) {
    return new Object[]
      {String.valueOf (weekNumber + 1),
       DateFormatter.formatDate (ScheduleEntry.dateOf (startDate, weekNumber)),
       String.valueOf (se.plannedTime / 60),
       String.valueOf (se.plannedCumTime / 60),
       stringDouble (se.plannedCumValue, EV_DECIMALS),
       formatTime (se.actualTime),
       formatTime (se.actualCumTime),
       stringDouble (se.actualCumEarnedValue, EV_DECIMALS)};
  }



  protected Object [] getTaskRow (TaskEntry te,
                                  int       myNumber) {
    return new Object[]
      {String.valueOf (myNumber),
       ((te.taskName == null) ? "" : te.taskName.path()),
       formatTime (te.plannedTime),
       stringDouble (te.plannedValue, EV_DECIMALS),
       formatTime (te.plannedCumTime),
       stringDouble (te.plannedCumValue, EV_DECIMALS),
       DateFormatter.formatDate (te.plannedDate),
       DateFormatter.formatDate (te.actualDate),
       stringDouble (te.actualEarnedValue, EV_DECIMALS)};
  }



  // Scan time log(s) for all time entered for the listed nodes during the
  // week that starts at time d.
  protected long getTimeFromWeekOf (TimeLog tl, Date d, Vector nodeList) {
    TimeLogEntry tle;
    long         totalTime = 0;
    Enumeration filt = tl.filter (PropertyKey.ROOT,
                                  d,
                                  ScheduleEntry.dateOf (d, 1));
    while (filt.hasMoreElements()) {
      tle = (TimeLogEntry)filt.nextElement();
      if (nodeList.contains (tle.key))
        totalTime += tle.minutesElapsed;
    }
    return totalTime;
  }



  // Scan data log(s) for all (listed) tasks marked complete for the week
  // specified.
  protected double getEarnedValueFromWeek (Date d, Vector taskLog) {
    TaskEntry te;
    Date      d2          = ScheduleEntry.dateOf (d, 1);
    double    earnedValue = 0.0;

    for (int i = 0; i < taskLog.size(); i++) {
      te = (TaskEntry)taskLog.elementAt (i);
      if (te.actualDate != null)
        if ((te.actualDate.equals (d) || te.actualDate.after (d)) &&
            te.actualDate.before (d2))
          earnedValue += te.actualEarnedValue;
    }
    return earnedValue;
  }



  protected Vector getNodeList () {
    Vector v = new Vector ();
    for (int ii = 0; ii < currentTaskLog.size(); ii++)
      v.addElement (((TaskEntry)currentTaskLog.elementAt (ii)).taskName);
    return v;
  }



  // Update the tables per current logs
  protected void updateTables()
  {
    JTable        aTable;
    VTableModel   model;
    ScheduleEntry se;
    Object        a[];
    int           rowCount;

    aTable = taskTable.table;
    model = (VTableModel)aTable.getModel();
    rowCount = model.getRowCount();
    for (int row = 0; row < currentTaskLog.size(); row++) {
      a = getTaskRow ((TaskEntry)currentTaskLog.elementAt (row), row + 1);
      if (row < rowCount)
        for (int col = 0; col < a.length; col++)
          model.setValueAt (a [col], row, col);
      else
        model.addRow(a);
    }
    aTable.validate();

    aTable = scheduleTable.table;
    model = (VTableModel)aTable.getModel();
    rowCount = model.getRowCount();
    Date sd = DateFormatter.parseDate (startDate.getText());
    for (int row = 0; row < currentScheduleLog.size(); row++) {
      a = getScheduleRow
        (row, sd,
         (ScheduleEntry)currentScheduleLog.elementAt (row));
      if (row < rowCount)
        for (int col = 0; col < a.length; col++)
          model.setValueAt (a [col], row, col);
      else
        model.addRow(a);
    }
    aTable.validate();
  }



  public void calculate () {
    long cumTime = 0;
    TaskEntry     te;
    ScheduleEntry se;

    //end any ongoing edit(s)
    if (taskTable.table.isEditing())
      taskTable.table.editingStopped
        (new ChangeEvent("Calculating: Stop edit"));
    if (scheduleTable.table.isEditing())
      scheduleTable.table.editingStopped
        (new ChangeEvent("Calculating: Stop edit"));

    for (int ii = 0; ii < currentTaskLog.size(); ii++) {
      te = (TaskEntry)currentTaskLog.elementAt (ii);
      cumTime += scanTask (te);
      te.plannedCumTime = cumTime;
    }

    double cpv = 0.0;
    for (int ii = 0; ii < currentTaskLog.size(); ii++) {
      te = (TaskEntry)currentTaskLog.elementAt (ii);
      if (cumTime != 0)
        te.plannedValue = (double)(te.plannedTime * 100) / (double)cumTime;
      else
        te.plannedValue = 0.0;
      te.plannedCumValue = cpv = cpv + te.plannedValue;
      te.actualEarnedValue = ((te.actualDate != null) ? te.plannedValue : 0.0);
    }

    long pct = 0;
    long actualCumTime = 0;
    int taskIndex = 0;
    double acev = 0.0, pcv = 0.0;
    Vector nodeList = getNodeList ();
    Date sd = DateFormatter.parseDate (startDate.getText());
    for (int ii = 0; ii < currentScheduleLog.size(); ii++) {
      se = (ScheduleEntry)currentScheduleLog.elementAt (ii);
      se.date = ScheduleEntry.dateOf (sd, ii);
      if (se.plannedTime != 0) {
        pct += se.plannedTime;
        se.plannedCumTime = pct;
        se.plannedCumValue = pcv;
        while ((taskIndex < currentTaskLog.size()) &&
               ((te = (TaskEntry)currentTaskLog.elementAt
                 (taskIndex)).plannedCumTime) <= pct) {
          te.plannedDate = se.date;
          se.plannedCumValue = pcv = te.plannedCumValue;
          taskIndex++;
        }
        //get actual time worked during the week
        actualCumTime += (se.actualTime = getTimeFromWeekOf (tl, se.date,
                                                             nodeList));
        se.actualCumTime = actualCumTime;
        acev += getEarnedValueFromWeek (se.date, currentTaskLog);
        se.actualCumEarnedValue = acev;
      }
    }
    updateTables();
  }



  protected long parseTime (String s) {
    int colon = s.indexOf (":");
    long lv = 0;
    if (colon >= 0) {
      try {
        lv = 60 * Long.valueOf (s.substring (0, colon)).longValue();
      } catch (Exception e) { }
      try {
        lv += Long.valueOf (s.substring (colon + 1)).longValue();
      } catch (Exception e) { }
    } else {
      try {
        lv = Long.valueOf (s).longValue();
      } catch (Exception e) { }
    }
    return lv;
  }



  protected String formatTime (long t) {
    if (t < 60)
      return String.valueOf(t);
    int min = (int) (t % 60);
    if (min < 10)
      return String.valueOf (t / 60) + ":0" + String.valueOf (min);
    return String.valueOf (t / 60) + ":" + String.valueOf (min);
  }



  public String hasID (String idList, String id, String sep) {
    StringTokenizer st = new StringTokenizer (idList, sep, false);
    String s, test = id + ".";
    while (st.hasMoreTokens()) {
      s = st.nextToken();
      if (s.startsWith (test))
        return s;
    }
    return null;
  }




  public void addID (Vector v, String id, PropertyKey key) {
    if (id == null)
      return;
    int idx = Integer.valueOf (id.substring
                               (id.lastIndexOf (".") + 1)).intValue();
    if (idx >= v.size())
      v.setSize (idx + 1);
    v.setElementAt (key, idx);
  }



  //does NOT check for replacement
  public void addID (PropertyKey pk, String id, int index) {
    Prop p = useProps.pget (pk);
    String s = p.getID();
    String t = ((s == null) ? "" : s + ID_SEP) + (id + "." + index);
    p.setID (t);
    useProps.put (pk, p);
  }



  public void deleteID (PropertyKey pk, String id, int index) {
    String  s, t  = "";
    boolean first = true;
    int     count = 0;
    Prop    p     = useProps.pget (pk);
    StringTokenizer st = new StringTokenizer (p.getID(), ID_SEP, false);
    while (st.hasMoreTokens()) {
      s = st.nextToken();
      if (count++ != index) {
        t = (first) ? s : t + ID_SEP + s;
        first = false;
      }
    }
    useProps.put (pk, p);
  }



  public void updateWeek (String id,
                          int    index,
                          long   plannedTime) {
    String wks = (String)taskProps.get (id + PT_WEEKS);
    Vector v = new Vector();
    if (wks != null) {
      StringTokenizer st = new StringTokenizer (wks, TAB, false);
      while (st.hasMoreTokens())
        v.addElement (st.nextToken());
    }
    if (v.size() <= index)
      v.setSize (index + 1);
    v.setElementAt ((String) ("" + plannedTime), index);
    wks = null;
    boolean first = true;
    for (int i = 0; i < v.size(); i++) {
      wks = ((first) ? "" : wks + TAB) + (String)v.elementAt (i);
      first = false;
    }
    taskProps.put (id + PT_WEEKS, wks);
  }



  public void deleteWeek (String id, int index) {
    String wks = (String)taskProps.get (id + PT_WEEKS);
    StringTokenizer st = new StringTokenizer (wks, TAB, false);
    Vector v = new Vector();
    while (st.hasMoreTokens())
      v.addElement (st.nextToken());
    if (v.size() > index) {
      v.removeElementAt (index);
      wks = null;
      boolean first = true;
      for (int i = 0; i < v.size(); i++) {
        wks = ((first) ? "" : wks + TAB) + (String)v.elementAt (i);
        first = false;
      }
      taskProps.put (id + PT_WEEKS, wks);
    }
  }



  // This method implements utilTableValidator
  public boolean validate (int        id,
                           int        row,
                           int        col,
                           String     newValue) {
    if (validateCell != null)
      return false;
    boolean rv = true;
    validateCell = "" + row + "," + col;
    switch (id) {
    case TASK_TABLE:
      TaskEntry te;
      try {
        te = (TaskEntry)currentTaskLog.elementAt (row);
      } catch (Exception e) { validateCell = null; return false; }
      switch (col) {
      case 2:                   // Planned Time
        try {
          String thePath = te.taskName.path();
          DoubleData pt = (DoubleData)data.getSimpleValue (thePath + PLANNED_TIME);
          if ((pt == null) || (pt.isEditable())) {
            long lv = parseTime (newValue);
            if (lv >= 0) {
              te.plannedTime = lv;
            } else {
              te.plannedTime = 0;
              rv = false;
            }
            data.putValue (thePath + PLANNED_TIME,
                           new DoubleData (te.plannedTime));
          }
          taskTable.table.setValueAt (formatTime (te.plannedTime), col, row);
        } catch (Exception e) { rv = false; }
        break;
      case 7:                   // Actual Date
        Date d = DateFormatter.parseDate (newValue);
        if (d == null) {
          rv = false;
          if (te.actualDate != null)
            taskTable.table.setValueAt (DateFormatter.formatDateTime
                                        (te.actualDate), col, row);
          else
            taskTable.table.setValueAt ("", col, row);
        } else {
          te.actualDate = d;
          DateData ad = new DateData (d, true);
          data.putValue (te.taskName.path() + COMPLETED_TIME, ad);
        }
        break;
      }
      break;

    case SCHEDULE_TABLE:
      ScheduleEntry se;
      try {
        se = (ScheduleEntry)currentScheduleLog.elementAt (row);
      } catch (Exception e) { validateCell = null; return false; }
      switch (col) {
      case 2:                   // Planned Time
        try {
          long lv = Long.valueOf (newValue).longValue();
          if (lv >= 0)
            se.plannedTime = lv * 60;
          else {
            se.plannedTime = 0;
            rv = false;
          }
          scheduleTable.table.setValueAt (String.valueOf (se.plannedTime / 60),
                                          col, row);
          updateWeek (taskSheetName, row, se.plannedTime);
        } catch (Exception e) { rv = false; }
        break;
      } // switch (col)
    } // switch (id)
    if (autoCalculateOn)
      calculate();
    validateCell = null;
    return rv;
  }



  public void clearTables () {
    JTable aTable = taskTable.table;
    VTableModel model = (VTableModel)aTable.getModel();
    if (aTable.getEditingRow() != -1)
      aTable.editingStopped (new ChangeEvent("Clearing table: Stop edit"));
    for (int i = model.getRowCount() - 1; i >= 0; i--)
      model.removeRow (i);
    currentTaskLog.setSize (0);

    aTable = scheduleTable.table;
    model = (VTableModel)aTable.getModel();
    if (aTable.getEditingRow() != -1)
      aTable.editingStopped (new ChangeEvent("Clearing table: Stop edit"));
    for (int i = model.getRowCount() - 1; i >= 0; i--)
      model.removeRow (i);
    currentScheduleLog.setSize (0);
  }




  public void loadSheet (String sheet) {
    clearTables();
    String taskList = (String)taskProps.get (TASK_KEY);

    Vector v = new Vector();
    String s;
    StringTokenizer st;
    s = (String)taskProps.get (sheet + PT_START);
    startDate.setText (s);
    s = (String)taskProps.get (sheet + PT_EXTERNAL);
    //Here we handle externally defined/imported sheets
    s = (String)taskProps.get (sheet + PT_WEEKS);

    Enumeration keys = useProps.keys();
    Prop        value;
    String      id;
    PropertyKey key;
    while (keys.hasMoreElements()) {
      key = (PropertyKey)keys.nextElement();
      value = (Prop)useProps.get (key);
      if (value != null)
        addID (v, hasID (value.getID(), sheet, ID_SEP), key);
    }
    PropertyKey pk;
    for (int i = 0; i < v.size(); i++) {
      pk = (PropertyKey)v.elementAt (i);
      if (pk != null)
        addTaskRow (pk);
      else {                    // check here for externals
      }
    }

    st = new StringTokenizer (s, TAB, false);
    while (st.hasMoreTokens())
      addScheduleRow (Long.valueOf (st.nextToken()).longValue());
  }



  public void createSheet (String s) {
    String taskList = (String)taskProps.get (TASK_KEY);
    if (taskList != null) {
      StringTokenizer st = new StringTokenizer (taskList, TAB, false);
      while (st.hasMoreTokens())
        if (st.nextToken().equals (s)) {
                                //Message to user - Can't create existing sheet
          JOptionPane.showMessageDialog
            (frame,
             "Cannot Create New Task Sheet With Existing Name.",
             "Task Sheet Creation Error",
             JOptionPane.PLAIN_MESSAGE);
          return;
        }
    }

    taskList = ((taskList == null) ? "" : taskList + TAB) + s;
    taskProps.put (TASK_KEY, taskList);
    taskNames.insertItemAt (s, 1);
    Date sd = ((startDate != null) ?
               DateFormatter.parseDate (startDate.getText()) : null);
    taskProps.put (s + PT_START, (sd != null) ? "" + sd.getTime() : "");
    taskProps.put (s + PT_EXTERNAL, "");
    taskProps.put (s + PT_WEEKS, "");
    loadSheet (s);
  }



  public void deleteSheet (String s) {
    String oldTaskList = (String)taskProps.get (TASK_KEY);
    String taskList = "";
    String tok;
    Object a;
    boolean first = true;
    boolean rv = true;

    if (oldTaskList != null) {
      StringTokenizer st = new StringTokenizer (oldTaskList, TAB, false);
      while (st.hasMoreTokens())
        if (!s.equals (tok = st.nextToken())) {
          taskList = (first) ? tok : taskList + TAB + tok;
          first = false;
        }
    }

    taskProps.put (TASK_KEY, taskList);
    a = taskProps.remove (s + PT_START);
    a = taskProps.remove (s + PT_EXTERNAL);
    a = taskProps.remove (s + PT_WEEKS);
    taskNames.removeItem (s);
    clearTables();
  }



  // return false if combo box should reset to "<none>"
  protected boolean selectTaskSheet () {
    int selIndex = taskNames.getSelectedIndex();
    int newIndex = taskNames.getItemCount() - 2;
    taskSheetName = null;
    boolean rv = false;

    if (selIndex == 0) {        // NO_SELECTION
      System.err.println ("Clearing ... ");
      clearTables();

    } else if (selIndex == newIndex) { // NEW_TOKEN
      String s = JOptionPane.showInputDialog
        (frame,
         "Enter New Task Sheet Name.",
         "Create Task Sheet",
         JOptionPane.PLAIN_MESSAGE);
      if (s != null) {
        System.err.println ("Creating " + s);
        createSheet (s);
      }

    } else if (selIndex == newIndex + 1) { // DELETE_TOKEN
      int nItems = taskNames.getItemCount() - 3;
      Object ar[] = new Object [nItems];
      for (int i = 0; i < nItems; i++)
        ar[i] = taskNames.getItemAt (i + 1);
      String s = (String)JOptionPane.showInputDialog
        (frame,
         "Select Task Sheet to Delete.",
         "Delete Task Sheet",
         JOptionPane.PLAIN_MESSAGE,
         null,
         ar,
         null);
      if (s != null) {
        System.err.println ("Deleting " + s);
        deleteSheet (s);
      }

    } else {                    // an actual selection - load it
      //TBD
      taskSheetName = (String)taskNames.getSelectedItem();
      System.err.println ("Loading " + taskSheetName);
      loadSheet (taskSheetName);
      rv = true;
    }
    calculate();
    return rv;
  }



  private JPanel constructHeaderPanel () {
    JPanel  retPanel = new JPanel(false);
    JButton button;
    JLabel  label;

    label = new JLabel ("Task Sheet:");
    retPanel.add (label);

    taskNames = new JComboBox ();

    taskNames.addItem (NO_SELECTION);
    if (taskProps != null) {    //Add list of available sheets
      String taskList = (String)taskProps.get (TASK_KEY);
      if (taskList != null) {
        StringTokenizer st = new StringTokenizer (taskList,
                                                  TAB,
                                                  false);
        while (st.hasMoreTokens())
          taskNames.addItem (st.nextToken());
      }
    }
    taskNames.addItem (NEW_TOKEN);
    taskNames.addItem (DELETE_TOKEN);
    taskNames.setSelectedIndex (0);
    //add the listener here
    taskNames.addActionListener (new ActionListener () {
      boolean mine = false;
      public void actionPerformed(ActionEvent e) {
        if (!mine) {
          if (!selectTaskSheet ()) {
            mine = true;
            taskNames.setSelectedIndex (0);
            mine = false;
          }
        }
      }
    });
    retPanel.add (taskNames);

    label = new JLabel (" Start Date:");
    retPanel.add (label);

    startDate = new JTextField ("", 10);
    DateChangeAction l = new DateChangeAction (startDate);
    startDate.addActionListener (l);
    startDate.addFocusListener (l);
    retPanel.add (startDate);

    autoCalc = new JCheckBox ("Auto Calculate");
    autoCalc.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) {
        autoCalculateOn = autoCalc.isSelected();
      }
    });
    retPanel.add (autoCalc);

    button = new JButton ("Calculate!");
    button.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) { calculate (); }
    });
    retPanel.add (button);

    return retPanel;
  }



  public void addTaskRow (PropertyKey pk) {
    JTable aTable = taskTable.table;
    VTableModel model = (VTableModel)aTable.getModel();

    if (aTable.getEditingRow() != -1)
      aTable.editingStopped (new ChangeEvent("Adding row: Stop edit"));

    Object aRow[];
    TaskEntry te = new TaskEntry ();
    te.taskName = pk;
    scanTask (te);

    aRow = getTaskRow (te, currentTaskLog.size() + 1);
    model.addRow(aRow);
    currentTaskLog.addElement (te);
    addID (pk, taskSheetName, currentTaskLog.size() - 1);
  }



  public void deleteSelectedTaskRow () {
    JTable aTable = taskTable.table;
    VTableModel model = (VTableModel)aTable.getModel();
    int rowBasedOn = aTable.getSelectedRow();
    if (rowBasedOn == -1) {
      if ((rowBasedOn = aTable.getEditingRow()) == -1)
        return;
      else
        aTable.editingStopped (new ChangeEvent("Deleting row: Stop edit"));
    }
    TaskEntry te = (TaskEntry)currentTaskLog.elementAt (rowBasedOn);
    model.removeRow (rowBasedOn);
    try {
      currentTaskLog.removeElementAt (rowBasedOn);
    } catch (Exception e) {}
    if (autoCalculateOn)
      calculate();
    deleteID (te.taskName, taskSheetName, rowBasedOn);
  }



  public void addScheduleRow (long hours) {
    JTable aTable = scheduleTable.table;
    VTableModel model = (VTableModel)aTable.getModel();

    // first try for selected row, else try for editing row, else try last row
    if (aTable.getEditingRow() != -1)
      aTable.editingStopped (new ChangeEvent("Adding row: Stop edit"));

    Object aRow[];
    ScheduleEntry se = new ScheduleEntry (hours * 60);
    long weekNumber = currentScheduleLog.size() + 1;
    Date sd = DateFormatter.parseDate (startDate.getText());
    aRow = getScheduleRow (weekNumber, sd, se);
    model.addRow(aRow);
    currentScheduleLog.addElement (se);
    updateWeek (taskSheetName, (int)weekNumber, hours);
  }



  public void addScheduleRow () {
    JTable aTable = scheduleTable.table;
    VTableModel model = (VTableModel)aTable.getModel();

    // first try for selected row, else try for editing row, else try last row
    int rowBasedOn = currentScheduleLog.size() - 1;
    if (aTable.getEditingRow() != -1)
      aTable.editingStopped (new ChangeEvent("Adding row: Stop edit"));

    Object aRow[];
    ScheduleEntry se;
    long hours = ((rowBasedOn == -1) ? 40 * 60 :
                  ((ScheduleEntry)currentScheduleLog.elementAt
                   (rowBasedOn)).plannedTime);
    se = new ScheduleEntry (hours);

    long weekNumber = currentScheduleLog.size() + 1;
    Date sd = DateFormatter.parseDate (startDate.getText());
    aRow = getScheduleRow (weekNumber, sd, se);
    model.addRow(aRow);
    currentScheduleLog.addElement (se);
    if (autoCalculateOn)
      calculate();
    updateWeek (taskSheetName, (int)weekNumber, hours);
  }



  public void deleteLastScheduleRow () {
    JTable aTable = scheduleTable.table;
    VTableModel model = (VTableModel)aTable.getModel();

    int lastRow = currentScheduleLog.size() - 1;
    if (lastRow == -1)
      return;
    if ((aTable.getEditingRow()) != -1)
      aTable.editingStopped (new ChangeEvent("Deleting row: Stop edit"));

    ScheduleEntry se = (ScheduleEntry)currentScheduleLog.elementAt (lastRow);
    model.removeRow (lastRow);
    try {
      currentScheduleLog.removeElementAt (lastRow);
    } catch (Exception e) {}
    if (autoCalculateOn)
      calculate();
    aTable.validate();
    deleteWeek (taskSheetName, lastRow);
  }



  public void queryAddExternalTask () {
    // (TBD) xxx
    // Bring up file selection dialog to allow selection of a "state" base
    // file.  after selection, read in file to get a list of allowable nodes
    // to select.  Then query as in queryAddTask(?).
  }



  // Note:  It would be nice if long lists were dropdown or at least
  // larger / resizeable, but that will have to wait until other
  // things are taken care of. (TBD)
  public void queryAddTask () {
    if (listOfNodes == null) {
      System.err.println("queryAddTask: node vector is null");
      return;
    }
    Object ar[] = new Object [listOfNodes.size()];
    try {
      listOfNodes.copyInto (ar);
    } catch (Exception ex) {System.err.println("queryAddTask: copy error");}
    Object o = JOptionPane.showInputDialog
      (frame,
       "Select Node to add.",
       "Add Tasking Node(s)",
       JOptionPane.PLAIN_MESSAGE,
       null,
       ar,
       null);
    if (o != null) {
      addTask ((String)o);
    }
  }



  private JPanel constructTaskPanel () {
    JButton button;

    taskTable = new ValidatingTable
      (new Object[] {" # ", "Task",
                     "PT", "PV", "PCT", "PCV", "PDate",
                     "Date", "EV"},
       null,
       new int[] {30, 200,
                  45, 35, 50, 35, 75,
                  75, 35},
       new String[] {"Task Number",                                  // Task #
                     "Task Name - The node the task is attached to", // Task
                     "Planned Time (hours)",                         // PT
                     "Planned Value",                                // PV
                     "Planned Cumulative Time (hours)",              // PCT
                     "Planned Cumulative Value",                     // PCV
                     "Planned Date",                                 // PDate
                     "Actual Date",                                  // Date
                     "Actual Earned Value"},                         // EV
       null, this, TASK_TABLE, true, null,
       new boolean[] {false, false,
                      true, false, false, false, false,
                      true, false});

    JPanel btnPanel = new JPanel(false);
    button = new JButton ("Add External...");
    button.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) { queryAddExternalTask (); }
    });
    btnPanel.add (button);

    button = new JButton ("Add...");
    button.addActionListener(new ActionListener () {
      public void actionPerformed(ActionEvent e) { queryAddTask (); }
    });
    btnPanel.add (button);

    button = new JButton ("Delete");
    button.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) { deleteSelectedTaskRow(); }
    });
    btnPanel.add (button);

    JPanel retPanel = new JPanel(false);
    retPanel.setLayout(new BorderLayout());
    retPanel.add ("Center", taskTable);
    retPanel.add ("South", btnPanel);

    Dimension d = new Dimension (taskTable.getPreferredSize());
    d.setSize (d.width,
               d.height + (2 * taskTable.table.getRowHeight()) +
               btnPanel.getPreferredSize().height + 5);
    retPanel.setMinimumSize (d);
    d.setSize (d.width,
               d.height + (Math.max (taskTable.table.getRowCount() - 2, 0) *
                           taskTable.table.getRowHeight()));
    retPanel.setPreferredSize (d);

    return retPanel;
  }



  private JPanel constructSchedulePanel () {
    JButton button;

    scheduleTable = new ValidatingTable
      (new Object[] {"Week #", "Date",
                     "PT", "PCT", "PCV",
                     "Time", "CT", "CEV"},
       null,
       new int[] {50, 100,
                  45, 50, 35,
                  60, 50, 35},
       new String[] {"Week Number",                        // Week #
                     "Date of first day in week (Monday)", // Task
                     "Planned Time (hours)",               // PT
                     "Planned Cumulative Time (hours)",    // PCT
                     "Planned Cumulative Value",           // PCV
                     "Actual Time (hours)",                // PDate
                     "Actual Cumulative Time (hours)",     // Date
                     "Actual Cumulative Earned Value"},    // EV
       null, this, SCHEDULE_TABLE, true, null,
       new boolean[] {false, false,
                      true, false, false,
                      false, false, false});

    JPanel btnPanel = new JPanel(false);
    button = new JButton ("Add");
    button.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) { addScheduleRow(); }
    });
    btnPanel.add (button);

    button = new JButton ("Delete Last");
    button.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) {
        deleteLastScheduleRow();
      }
    });
    btnPanel.add (button);

    JPanel  retPanel = new JPanel(false);
    retPanel.setLayout(new BorderLayout());
    retPanel.add ("Center", scheduleTable);
    retPanel.add ("South", btnPanel);

    Dimension d = new Dimension (scheduleTable.getPreferredSize());
    d.setSize (d.width,
               d.height + (2 * scheduleTable.table.getRowHeight()) +
               btnPanel.getPreferredSize().height + 5);
    retPanel.setMinimumSize (d);
    d.setSize(d.width,
              d.height + (Math.max (scheduleTable.table.getRowCount() - 2, 0) *
                          scheduleTable.table.getRowHeight()));
    retPanel.setPreferredSize (d);

    return retPanel;
  }



  private JPanel constructControlPanel () {
    JPanel  retPanel = new JPanel(false);
    JButton button;

    button = new JButton ("Print");
    retPanel.add (button);
//    button.addActionListener (new PrintAction ());

    button = new JButton ("Chart");
    retPanel.add (button);
//    button.addActionListener (new ChartAction ());

    button = new JButton ("Close");
    retPanel.add (button);
    button.addActionListener(new CloseAction());

    return retPanel;
  }



  public void show() {
    try {
      tl.read (dashboard.getTimeLog());
    } catch (IOException e) {}
    frame.show();
  }


                                // make sure root is expanded
  public void expandRoot () { tree.expandRow (0); }



  // Returns the TreeNode instance that is selected in the tree.
  // If nothing is selected, null is returned.
  protected DefaultMutableTreeNode getSelectedNode() {
    TreePath   selPath = tree.getSelectionPath();

    if(selPath != null)
      return (DefaultMutableTreeNode)selPath.getLastPathComponent();
    return null;
  }



  /**
    * The next method implement the TreeSelectionListener interface
    * to deal with changes to the tree selection.
    */
  public void valueChanged (TreeSelectionEvent e) {
    TreePath tp = e.getNewLeadSelectionPath();

    if (tp == null) {           // deselection
      tree.clearSelection();
      return;
    }
    Object [] path = tp.getPath();
    PropertyKey key = treeModel.getPropKey (useProps, path);

    Prop val = useProps.pget (key);
  }



  // DateChangeAction responds to user input in a date field.
  class DateChangeAction implements ActionListener, FocusListener {
    JTextComponent widget;
    String         text = null;
    Color          background;

    public DateChangeAction (JTextComponent src) {
      widget = src;
      text = widget.getText();
      background = new Color (widget.getBackground().getRGB());
    }

    protected void validate () {
      String newText = widget.getText();

      Date d = DateFormatter.parseDate (newText);
      if (d == null) {
        if ((newText != null) && (newText.length() > 0))
          widget.setBackground (Color.red);
        else {
          widget.setBackground (background);
          text = newText;
          widget.setText (text);
          if (autoCalculateOn)
            calculate();
        }
      } else {
        widget.setBackground (background);
        text = DateFormatter.formatDate (d);
        widget.setText (text);
        if (autoCalculateOn)
          calculate();
      }
      widget.repaint(widget.getVisibleRect());
    }

    public void actionPerformed(ActionEvent e) { // hit return
      validate();
    }

    public void focusGained(FocusEvent e) {
      widget.selectAll();
    }

    public void focusLost(FocusEvent e) {
      validate();
    }

  } // End of TaskTemplate.DateChangeAction


  //
  // CloseAction responds to user clicking Close button.
  //
  class CloseAction extends Object implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      //if editing, stop edits
      if (taskTable.table.isEditing())
        taskTable.table.editingStopped
          (new ChangeEvent("Saving Data: Stop edit"));
      if (scheduleTable.table.isEditing())
        scheduleTable.table.editingStopped
          (new ChangeEvent("Saving Data: Stop edit"));
                                // save the task & schedule logs
      save();
      frame.setVisible (false);
    }
  } // End of TaskTemplate.CloseAction


}
TOP

Related Classes of pspdash.TaskTemplate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.