# Java: Example - Raise.java

This program program was inspired by a Gore-Bush ballots in Florida. The `paintComponent` method looks too complicated and could be improved. Also, there's no need to redraw all the fixed elements; these could be drawn only once and saved in a BufferedImage.

## The main program / applet

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
    // File: wantRaise/Raise.java
    // Description: Applet+application to ask employee if they want a raise.
    //              Example of mouse listeners, borderlayout, ...
    // Author: Fred Swartz
    // Date:   2005-02-03 2000-12-01 ... 2002-02-19

    package wantraise;

    import javax.swing.*;

    ////////////////////////////////////////////////////////////////////// Raise
    public class Raise extends JApplet {

        //=================================================== applet constructor
        public Raise() {
            add(new RaiseGUI());
        }

        //================================================================= main
        public static void main(String[] args) {
            JFrame w = new JFrame("Employee Survey");
            w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            w.setContentPane(new RaiseGUI());
            w.setResizable(false);
            w.pack();
            w.setVisible(true);
        }
    }

## The GUI panel

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
    // File: wantRaise/RaiseGUI.java
    // Description: Panel to display the raise info
    // Author: Fred Swartz
    // Date:   2005-02-03 2000-12-01 ... 2002-02-19

    package wantraise;

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;

    //////////////////////////////////////////////////////////////// RaiseGUI
    class RaiseGUI extends JPanel {
        private SurveyForm survey = new SurveyForm();

        //======================================================== constructor
        public RaiseGUI() {
            //... Create components
            JButton resetButton = new JButton("Reset");
            // To make label background blue, put it on a blue panel.
            JLabel title = new JLabel("Want a Raise?", JLabel.CENTER);
            title.setFont(new Font("Serif", Font.BOLD, 48));
            title.setForeground(Color.white);
            JPanel titlePanel = new JPanel();
            titlePanel.setBackground(Color.blue);
            titlePanel.add(title);

            //... Add listener to button
            resetButton.addActionListener(new ResetListener());

            //... Layout components
            this.setLayout(new BorderLayout());
            this.add(titlePanel , BorderLayout.NORTH);
            this.add(survey     , BorderLayout.CENTER);
            this.add(resetButton, BorderLayout.SOUTH);
        }

        //================================================ inner class listener
        private class ResetListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                survey.reset(false);
            }
        }
    }

## The Graphics panel that draws the "buttons"

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    // File: wantRaise/SurveyForm.java
    // Description: Panel draws form, uses mouse listeners.
    // Author: Fred Swartz
    // Date:   2005-02-03 2000-12-01 ... 2002-02-19

    package wantraise;

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;

    /////////////////////////////////////////////////////////// class SurveyForm
    class SurveyForm extends JPanel implements MouseMotionListener {
        private final int RADIUS     = 16;  // Radius of both buttons
        private final int DIAM       = 2* RADIUS;

        private boolean m_isNoRaiseSelected = false; // set true after button selected
        private int     m_buttonX;  // x-coord of movable button.
        private int     m_buttonY;
        private int m_x = 0; // The mouse coords set by mouse listeners.
        private int m_y = 0; // paintComponent uses them to calc No Raise pos.

        //========================================================== constructor
        public SurveyForm() {
            this.setBackground(Color.white);
            this.setPreferredSize(new Dimension(300, 230));
            this.setFont(new Font("Serif", Font.BOLD, 48));
            this.addMouseMotionListener(this);
        }

        //================================================================ reset
        public void reset(boolean isNoRaiseSelected) {
            // Called from "outside" to clear the status..
            m_isNoRaiseSelected = isNoRaiseSelected;
            this.repaint();       // Repaint to show change.
        }

        //======================================================= paintComponent
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            //... Use constants to make changes+debugging easier.
            final int LABEL_X   = 20;    // x coord of both labels
            final int BUTTON_X  = 240;   // x coord of both buttons
            final int CRITICAL_DIST = 3 * RADIUS;
            final int SIDE      = 6 * RADIUS;
            final int LEFT      = BUTTON_X - CRITICAL_DIST;

            //... No Raise button info
            final int NORAISE_Y = 80;  // y coord of NoRaise button

            //... Top and bottom of area that affects  Raise button
            final int RAISE_Y   = NORAISE_Y + 100;
            final int CENTER_Y  =   RAISE_Y - RADIUS; // Default y coord of Raise

            final Rectangle NR_BOUNDS = new Rectangle(LEFT, NORAISE_Y-CRITICAL_DIST, SIDE, SIDE);
            final Rectangle  R_BOUNDS = new Rectangle(LEFT,   RAISE_Y-CRITICAL_DIST, SIDE, SIDE);

            //... Draw button labels.
            g.setColor(Color.black);
            g.drawString("No Raise", LABEL_X, NORAISE_Y);
            g.drawString("Raise"   , LABEL_X,   RAISE_Y);

            //... Check if near "No Raise" button, and "select" it if so.
            if (m_isNoRaiseSelected || NR_BOUNDS.contains(m_x, m_y)) {
                //... Draw selected No Raise button and unselected Raise button
                g.fillOval(BUTTON_X-RADIUS, NORAISE_Y-DIAM, DIAM, DIAM);
                g.drawOval(BUTTON_X-RADIUS,   RAISE_Y-DIAM, DIAM, DIAM);
                m_isNoRaiseSelected = true; // "Select" No Raise button.

            } else {
                //... Draw empty No Raise button (doesn't depend on mouse position)
                g.drawOval(BUTTON_X-RADIUS, NORAISE_Y-DIAM, DIAM, DIAM);

                //... Draw Raise button (depends on mouse position)
                m_buttonX = BUTTON_X;// Assume default position; may change.
                m_buttonY = CENTER_Y;

                if (R_BOUNDS.contains(m_x, m_y)) {
                    //... Mouse is near the Raise button, so we may move it
                    int xDisplacement = BUTTON_X - m_x;
                    int yDisplacement = CENTER_Y - m_y;

                    //... Compute distance of mouse from center.
                    double mouseDist = Math.sqrt(xDisplacement * xDisplacement
                                               + yDisplacement * yDisplacement);
                    if (mouseDist < CRITICAL_DIST) {
                        // ... It's within the critical radius.
                        double bdist = CRITICAL_DIST - mouseDist;
                        double ratio = 1.0;
                        if (mouseDist > 1.0) {
                            ratio = bdist / mouseDist; // Avoid div by 0.0
                        }

                        m_buttonX = BUTTON_X + (int)(ratio * xDisplacement);
                        m_buttonY = CENTER_Y + (int)(ratio * yDisplacement);
                    }
                }
                g.drawOval(m_buttonX-RADIUS, m_buttonY - RADIUS, DIAM, DIAM);
            }
        }

        //================================================== mouseMoved listener
        public void mouseMoved(MouseEvent e) {
            this.m_x = e.getX();
            this.m_y = e.getY();
            this.repaint();
        }

        //================================================== mouseMoved listener
        /* Drag listener to prevent sneaking onto Raise button. */
        public void mouseDragged(MouseEvent e) {
            mouseMoved(e);
        }
    }