Jump to content

Grinding6.java

From EDM2
Revision as of 16:31, 20 December 2017 by Ak120 (talk | contribs) (Ak120 moved page Grinding Java - Enhancing the AWT:grinding6.java to Grinding6.java)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
package GUITools;
import GUITools.ImageButton;

import java.AWT.*;
import java.AWT.event.*;
import java.util.Vector;
/**
 * Dockable toolbar class written by Shai Almog 1996.
 * revised for JDK 1.1.1 in 4/97.
 * The sorce is in the public domain and may be modified and used freely.
 * It is not a requirment but I would consider it good manners if you credit me
 * and EDM/2 (www.edm2.com) in applications in which this code was used ;-)
 * The Dockable toolbar class creats a toolbar container that can be torn
 * off the Frame holding it and left to hover above it.
 * It's based on the panel and Window classes and it must be put
 * on a frame.
 * A problem with the Dockable toolbar is the way different implementations
 * of the JDK treat the Window class. This creates a highly an portable
 * implementation, the solution was to abstract everything and hope that
 * a future implementation of the JDK solves this problem.
**/

public class DockableToolbar extends
java.AWT.Panel implements ActionListener, MouseMotionListener, MouseListener
{
 public DockableToolbar(Frame Owner) // Owner is the component who own's the Toolbar.
 {
  this.Owner = Owner; // This is an easy trick to avoid confusion with parameters
          // This way you don't have to invent a name for every parameter.
  setLayout(new FlowLayout()); // The flow layout just put's the  Components
         // one after the other as best as it can. No better is needed here.
  addToolbarToOwner(); // This method will add the panel and the frame to
  addMouseMotionListener(this);
  addMouseListener(this);
 }

 /**
  * This method gets called when an event occurs in the Components we
  * are listenting too, since we are listening to the Container and all
  * of the buttons all of their events reach us.
  * I'd like too seprate the event handeling here from the implementation
  * but it's not practical due to it's heavyconnection to the Component.
 **/
 public void actionPerformed(ActionEvent E)
 {
  if(E.getSource() instanceof Button) // If the event source is a button
   sendEvent(whichButtonGotPressed((Button)E.getSource()));
 }

 /**
  * This method allows an object to listen to events dispatched by the toolbar,
  * in a similar way to listening to events dispatched by buttons.
 **/
 public void addActionListener(ActionListener listener)
 {
  listOfActionListeners.addElement(listener);
 }

 public void addButton(Button B) // This method adds a button to the Toolbar.
 {
  add(B);
  listOfButtons.addElement((Object)B);
  B.addActionListener(this); // Listening to action events on the button (mouse clicks).
  B.addMouseMotionListener(this); // Listening to mouse motion events on the
                                  // button (for Tooltips).
  B.addMouseListener(this); // Listening to mouse events on the
                            // button (for dropping dragged Toolbars).
 }

 public void addButton(String caption) // Creats a Button with the label = caption.
 {
  addButton(new Button(caption));
 }

 private void addToolbarToOwner() // This method will add the panel to the
                                  // Toolbar Container.
 {
  Owner.add(this);
 }

 /**
  * This method detaches the toolbar, and leaves it hanging above the Frame.
 **/
 public void detachToolbar()
 {
   if (detachedToolbar != null)
   {
        dockToolbar();
        return;
   }
  detachedToolbar = new Window(Owner); // Creating the Window that will hold the Toolbar.
  detachedToolbar.setLayout(new BorderLayout()); // We will only have one
     // component in the frame (the Panel), but it's best to do it this way.
  detachedToolbar.add("South", this); // We add this (the Panel) to the frame yet keep
                                      // it hidden.
  Owner.remove(this); // Removing the Panel from the Toolbar.

  systemSpecificToolbarCalibration(); // This is the part that initializes the Window.
    // I had a rough time with it ,so I dumped it into a seprate method so it can
    // be modified with ease.

  detachedToolbar.show(); // Show the hovering Toolbar.
  Owner.pack(); // Arrange the components in the original Container.
 }

 /**
  * This method reattaches the toolbar to the owner frame.
 **/
 public void dockToolbar()
 {
  if (detachedToolbar == null)
  {
    detachToolbar();
    return;
  }
  Owner.add(this);
  Owner.pack(); // Sort the Components in the Container.
  detachedToolbar.removeAll();
  detachedToolbar.dispose();  // Destroy the hovering window.
  detachedToolbar = null; // this is so we can tell if the toolbar is docked.
 }

 public boolean isDocked() // This method returns true if the toolbar is not hovering.
 {
  return (detachedToolbar == null);
 }

 public void mouseClicked(MouseEvent e)
 {
  // This method must be implemented to support the MouseListener interface.
 }

 /**
  * This method is called in an event of a mouse drag.
  * It can happen for 2 reasons:
  * 1. The Toolbar is torn from place.
  * 2. The Toolbar is being dragged, remember the Window class is not
  * like the Frame class, it cannot be dragged by default.
 **/
 public void mouseDragged(MouseEvent e)
 { // We use this method to detach the toolbar and to move it.
  if (detachedToolbar == null) // If the toolbar is docked.
   detachToolbar(); // Then it's being torn off, detach it.
  else // If the toolbar is detached then we are trying to drag it.
  {
   // We comute the X and Y where to drag it too.
   // This is not simple since the X and Y we are give is relative to the
   // Component which is the window.
   if(lastYLocationOnDrag == -1)
   {
    lastYLocationOnDrag = e.getY();
    lastXLocationOnDrag = e.getX();
   }
   else
   {
    int x = detachedToolbar.getLocation().x + e.getX() - lastXLocationOnDrag,
     y = detachedToolbar.getLocation().y + e.getY() - lastYLocationOnDrag;
    lastYLocationOnDrag = -1;
    lastXLocationOnDrag = -1;
    detachedToolbar.setLocation(x,y);
    repaint();
   }
  }
 }

 public void mouseEntered(MouseEvent e)
 {
  // This method must be implemented to support the MouseMotionListener interface.
 }

 public void mouseExited(MouseEvent e)
 {
  // This method must be implemented to support the MouseMotionListener interface.
 }

 public void mouseMoved(MouseEvent e)
 {
  // This method must be implemented to support the MouseMotionListener interface.
 }

 public void mousePressed(MouseEvent
e)
 {
  // This method must be implemented to support the MouseListener interface.
 }

 /**
  * This method could mean the end of a drag operation. So here we use it to
  * drop the Toolbar, if it's being dragged.
 */
 public void mouseReleased(MouseEvent e)
 {
  if(lastYLocationOnDrag != -1)
  {
   int x = detachedToolbar.getLocation().x + e.getX() - lastXLocationOnDrag,
    y = detachedToolbar.getLocation().y + e.getY() - lastYLocationOnDrag;
    lastYLocationOnDrag = -1;
    lastXLocationOnDrag = -1;
   detachedToolbar.setLocation(x,y);
   repaint();
  }
 }

 /**
  * This method sends the button pressed event to all listeners.
  * It's needed so that an application can listen to the toolbar without
  * maintaining logic for all the Buttons on it.
 **/
 private void sendEvent(int idOfTheButtonPressed)
 {
  ActionListener currentListener;
  ActionEvent E = new
      ActionEvent(listOfButtons.elementAt(idOfTheButtonPressed),
      ActionEvent.ACTION_PERFORMED,
      Integer.toString(idOfTheButtonPressed));
  for (int counter = 0; counter < listOfActionListeners.size(); counter++)
  {
   currentListener = (ActionListener)listOfActionListeners.elementAt(counter);
   currentListener.actionPerformed(E);
  }
 }

 /**
  * This method is used by the detachToolbar method to handle the Window class.
  * The reason this is in a seprate class is to abstaract the incompatible behavior
  * among JDK versions.
 **/
 private void systemSpecificToolbarCalibration()
 {
  detachedToolbar.pack();
  Dimension windowSize = detachedToolbar.getSize(),
      buttonSize = ((Component)listOfButtons.elementAt(0)).getSize();
  detachedToolbarTitleBar = new ToolbarTitleBar(windowSize.width,TOOLBAR_TITLEBAR_HEIGHT);

  detachedToolbar.add("North", detachedToolbarTitleBar);
  detachedToolbar.pack();
 }

 /**
  * This method was originally used to send the button pressed events, but now
  * I use it to check the button offset for a button ID.
 **/
 private int whichButtonGotPressed(Button B)
 { // This method returns the Buttons offset in the vector.
  for (int counter = 0; counter < listOfButtons.size() ; counter++)
   if(listOfButtons.elementAt(counter) == B)
    return(counter);
  return(-1);
 }

 private Window detachedToolbar = null; // This is the hovering Toolbar.
 private ToolbarTitleBar detachedToolbarTitleBar; // This is the Tile bar of the Toolbar.
 private Vector listOfTooltips = new Vector(); // This is a list of the Tooltip strings.
 private Vector listOfActionListeners = new Vector(); // This is a list of the classes
                                                      // that listen to toolbar events.
 private Vector listOfButtons = new Vector(); // This is a list of the buttons.
 private Frame Owner; // This is the Frame the Toolbar is located on.
 private int lastXLocationOnDrag = -1;       // These two variables are used for
                                             // dragging the toolbar.
 private int lastYLocationOnDrag = -1;
 private static final int TOOLBAR_TITLEBAR_HEIGHT = 5; // This is the height
                                                       // of the toolbars title bar.
}



/**
 * This class is for internal use only. It paints the title on top of
 * the detached window.
 * The Window class is just a Canvas with no title to grab on to and this
 * canvas makes it look similar.
**/
class ToolbarTitleBar extends Canvas
{
 ToolbarTitleBar(int width, int height)
 {
  super();
  setSize(width,height); // Canvas on the window top in 3 pixel hight.
  this.height = height;
  this.width = width;
 }

 public void paint(Graphics g)
 {
  g.setColor(SystemColor.activeCaption); // The SystemColor class contains
                                         // colors specific to this system.
  g.fillRect(0,0,width,i);
 }

 private   int height;
 private   int width;
}