Package pspdash

Source Code of pspdash.HierarchyButton$MyMenuItem

// 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 java.awt.Toolkit;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import pspdash.data.DataEvent;
import pspdash.data.DataListener;
import pspdash.data.DateData;

public class HierarchyButton implements ActionListener {

    PSPDashboard parent = null;
    JMenu menu = null;
    HierarchyButton child = null;
    PropertyKey self = null;
    int numChildren = 0;

    private void debug(String msg) {
      // System.out.println(msg);
    }


    HierarchyButton(PSPDashboard dash, PropertyKey useSelf) {
        super();
        parent = dash;
        self = useSelf;
        //if (self != null)
          //debug (self.toString());

        String s;
        PSPProperties props = parent.getProperties ();

        //debug("Getting numChildren:"+self);
        numChildren = props.getNumChildren (self);
        //debug("numChildren:"+numChildren);

        if (numChildren != 0) {

          //debug("Processing children:"+numChildren);

          menu = new JMenu();
          PCSH.enableHelpKey(parent.hierarchy_menubar, "HierarchyMenus");
          //PCSH.enableHelpKey(menu, "HierarchyMenus");

          parent.hierarchy_menubar.add(menu);
          parent.hierarchy_menubar.invalidate();

          int i;
          for (i=0; i<numChildren; i++) {
            //debug("Getting child " + i + " of "+numChildren);
            PropertyKey key = props.getChildKey (self, i);
            //debug(" key:"+key.key()+": = "+props.getChildName (self, i));
            menu.add(new MyMenuItem(key));
          }

          selectChild(props.getChildName(self, props.getSelectedChild(self)));

        } else {
          parent.setCurrentPhase(self);
          parent.validate();
          parent.pack();
        }

    }



    // Destroy the entire hierarchy, but ensure the data for the current phase
    // has been saved.
    protected void terminate() {

        // save any data from the current phase
        parent.setCurrentPhase(self);

        // destroy the hierarchy
        delete();
    }



    protected void delete() {
      if (child != null) {
        child.delete();
        child = null;
        parent.hierarchy_menubar.remove(menu);
        for (int i = menu.getItemCount();  i-- > 0; )
            if (menu.getItem(i) instanceof MyMenuItem)
                ((MyMenuItem) menu.getItem(i)).delete();
        menu = null;
      }
    }

    public boolean setPath(String path) {
        if (path == null || path.length() == 0) return true;

        // remove the / from the beginning, if it is present.
        if (path.charAt(0) == '/')
            path = path.substring(1);

        String childName, rest;
        int slashPos = path.indexOf('/');

        if (slashPos == -1) {
            childName = path;
            rest = null;
        } else {
            childName = path.substring(0, slashPos);
            rest = path.substring(slashPos+1);
        }

        if (selectChild(childName))
            return child.setPath(rest);
        else
            return false;
    }

    public boolean setPhase(String phase) {
        if (phase == null || phase.length() == 0) return true;

        // If this is the terminal HierarchyButton without a menu, we
        // cannot set the phase.  return false.
        if (child == null) return false;

        // If our child has children, unconditionally delegate this task.
        if (child.numChildren != 0)
            return child.setPhase(phase);

        else
            // our child has no children.  We must be the HierarchyButton
            // with the rightmost visible menu.
            return selectChild(phase);
    }


    /** Select the child with the given name.
     *
     * @return true if the selection was successful, false if no child
     * with the given name exists.
     */
    boolean selectChild(String name) {
        //debug("selectChild.name = " + self + name);

        PSPProperties props = parent.getProperties ();
        int i;
        int sel = 0;
        for (i=0; i<numChildren; i++)
          if (name.equals(props.getChildName (self, i))) {
            sel = i;
            break;
          }

        if (i == numChildren) // didn't find the named child?
            return false;

        if ((child != null) && (props.getSelectedChild (self) == sel))
          return true;

        //debug("deleting old child");
        if (child != null) child.delete();

        props.setSelectedChild (self, sel);
        menu.setText(name);
        menu.invalidate();

        //debug("creating new child"+sel);
        child = new HierarchyButton (parent, new PropertyKey (self, name));
        return true;
    }

    public void workPerformed(DateData d) {
          // calculate the name of the Start Date data element for our path.
      String dataName = parent.data.createDataName(self.path(), "Started");

          // if our start date has not already been set, set it to d
      if (parent.data.getValue(dataName) == null)
        parent.data.putValue(dataName, d);

          // pass info down to child, as well.
      if (child != null) child.workPerformed(d);
    }


    private void markCompleted() {
          // mark this phase as completed in the data repository.
      String dataName = getCompletedDataname(self);
      parent.data.userPutValue(dataName, new DateData());
    }

    private String getCompletedDataname(PropertyKey key) {
        return parent.data.createDataName(key.path(), "Completed");
    }


    // When the user completes the last task in a series (e.g. Postmortem or
    // Reassessment), what should we do next?
    //
    // Set this variable to true to enable an odometer-style rollover -
    // that is, when completing the <b>last</b> task in the <b>last</b>
    // hierarchy menu, ask the second-to-last menu to increment (and so-on,
    // recursively up the list of menus).
    //
    // If this variable is set to false, the dashboard will instead leave
    // the hierarchy menus alone, and just stop the timer if it is running.
    public static final boolean ODOMETER_STYLE = false;



    public boolean selectNext() {

          // first, try to delegate this task to our child.  If the child is
          // able to perform a selectNext, we're done.
      if ((child != null) && child.selectNext()) return true;

          // if this is the terminal HierarchyButton without a menu, we
          // cannot perform selectNext.  Return false.
      if (child == null) { markCompleted(); return false; }

          // if odometer-style rollover is disabled, and our child has
          // children, we shouldn't rollover.  Return false.
      if (!ODOMETER_STYLE && child.numChildren != 0) { return false; }

          // calculate the number position of the next item to be selected.
      PSPProperties props = parent.getProperties ();
      int sel = props.getSelectedChild (self) + 1;

          // if that item is past the end of our list, we cannot perform
          // selectNext. Return false.
      if (sel == numChildren) { /*markCompleted();*/ return false; }

          // select the next item on our menu.
      selectChild(props.getChildName (self, sel));

      // Here's a philosphical question concerning the situation When our
      // child "rolls over" - i.e., our child already had his last item
      // selected, and thus wants us to increment our menu instead.  We just
      // incremented our menu with the line above.  Do we now want to force
      // our new child to select its first element?  That would make sense in
      // a mathematical sense.  In practice, however, I think it isn't the
      // right thing to do.  People don't usually follow processes in
      // flowchart order - instead, they may need to bounce around a bit.  For
      // example, if the user just completed a cycle of an SCR/PSP3 process,
      // move them into the next cycle, but don't require them to start that
      // cycle from the beginning if they have already performed some work
      // there.  Similarly, if the user just completed an entire project, move
      // the menu to the next project, but don't start that project over from
      // the beginning if they have already performed work there.
      //
      // So, with the above rationale, the following line is commented out.
      // If someone feels the mathematical behavior would be better, uncomment
      // the next line, as well as the definition of the procedure
      // selectFirst, below.
      //
      // child.selectFirst();

      return true;
    }



//     public void selectFirst() {
//       if (child != null) {
//      selectChild(parent.getProperties().getChildName(self, 0));
//      child.selectFirst();
//       }
//     }



    public void actionPerformed(ActionEvent e) {
      selectChild( ((JMenuItem)e.getSource()).getText() );
    }


    class MyMenuItem extends JMenuItem implements DataListener {
        String dataname;
        MyMenuItem(PropertyKey key) {
            super(key.name());
            addActionListener(HierarchyButton.this);
            setHorizontalTextPosition(SwingConstants.LEFT);
            dataname = getCompletedDataname(key);
            if (SHOW_CHECKMARKS) {
                //System.out.println("addDataListener("+dataname+")");
                parent.data.addDataListener(dataname, this);
            }
        }
        public void dataValueChanged(DataEvent e) {
            final Icon i =
               ((e.getValue() != null && e.getValue().test())
                   ? CHECKMARK_ICON : null);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() { setIcon(i); } } );
        }
        public void dataValuesChanged(Vector v) {
            for (int i = v.size();   i-- > 0; )
                dataValueChanged((DataEvent) v.get(i));
        }
        public void delete() {
            if (SHOW_CHECKMARKS) {
                //System.out.println("removeDataListener("+dataname+")");
                parent.data.removeDataListener(dataname, this);
            }
        }
    }
    private static final String CHECKMARK_SETTING_NAME = "setting";
    private static boolean SHOW_CHECKMARKS =
        !"false".equalsIgnoreCase(Settings.getVal(CHECKMARK_SETTING_NAME));

    private static final ImageIcon CHECKMARK_ICON =
        new ImageIcon(HierarchyButton.class.getResource("check.gif"));


    /** Scans the hierarchy tree and cleans up "garbage" completion flags
     * that were left around by completion-button logic in v1.3
     */
    public void cleanupCompletionFlags() {
        cleanupCompletionFlags(parent.getProperties(), PropertyKey.ROOT);
    }
    protected void cleanupCompletionFlags(PSPProperties props,
                                          PropertyKey key) {
        Prop val = props.pget(key);

        // no need to cleanup flags defined in project-level datafiles
        String dataFile = val.getDataFile();
        if (dataFile != null && dataFile.length() > 0)
            return;

        // no need to cleanup flags for leaves of the hierarchy
        int i = props.getNumChildren (key);
        if (i == 0)
            return;

        // cleanup the flag for this node in the hierarchy
        String flagName = getCompletedDataname(key);
        if (parent.data.getValue(flagName) != null)
            parent.data.putValue(flagName, null);

        // recurse through the hierarchy tree.
        while (i-- > 0)
            cleanupCompletionFlags(props, props.getChildKey (key, i));
    }
}
TOP

Related Classes of pspdash.HierarchyButton$MyMenuItem

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.