Skip to content

Commit 263db14

Browse files
refactor: replace MouseListener if/else chain with ActionListeners on timeline buttons
The seven timeline buttons (play, pause, stop, prev, next, slow, fast) were wired through a single MouseListener that identified which button was clicked by comparing e.getComponent() references in an if/else chain. This is fragile and contrary to Swing best practices — JButton clicks should use ActionListener. Extracted a createTimelineButton() helper that: - Creates the button with its icon in one call - Attaches an ActionListener directly (proper Swing pattern) - Adds tooltip text for accessibility - Eliminates ~70 lines of boilerplate
1 parent 907d4ca commit 263db14

1 file changed

Lines changed: 60 additions & 96 deletions

File tree

Gvisual/src/gvisual/Main.java

Lines changed: 60 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,104 +1453,47 @@ public final void initializeTimeLine() {
14531453

14541454

14551455

1456-
playButton = new JButton();
1457-
pauseButton = new JButton();
1458-
stopButton = new JButton();
1459-
prevButton = new JButton();
1460-
nextButton = new JButton();
1461-
slowButton = new JButton();
1462-
fastButton = new JButton();
1463-
1464-
String playImgPath = "images/play.png";
1465-
String pauseImgPath = "images/pause.png";
1466-
String stopImgPath = "images/stop.png";
1467-
String slowImgPath = "images/slow.png";
1468-
String fastImgPath = "images/fast.png";
1469-
String prevImgPath = "images/prev.png";
1470-
String nextImgPath = "images/next.png";
1471-
1472-
Icon play = new ImageIcon(playImgPath);
1473-
Icon pause = new ImageIcon(pauseImgPath);
1474-
Icon stop = new ImageIcon(stopImgPath);
1475-
Icon prev = new ImageIcon(prevImgPath);
1476-
Icon next = new ImageIcon(nextImgPath);
1477-
Icon slow = new ImageIcon(slowImgPath);
1478-
Icon fast = new ImageIcon(fastImgPath);
1479-
1480-
playButton.setIcon(play);
1481-
pauseButton.setIcon(pause);
1482-
stopButton.setIcon(stop);
1483-
prevButton.setIcon(prev);
1484-
nextButton.setIcon(next);
1485-
slowButton.setIcon(slow);
1486-
fastButton.setIcon(fast);
1487-
1488-
1489-
1490-
MouseListener clickListener = new MouseListener() {
1491-
1492-
public void mouseClicked(MouseEvent e) {
1493-
//throw new UnsupportedOperationException("Not supported yet.");
1494-
}
1495-
1496-
public void mousePressed(MouseEvent e) {
1497-
//throw new UnsupportedOperationException("Not supported yet.");
1498-
if (e.getComponent() == playButton) {
1499-
LOGGER.fine("Play pressed");
1500-
timer.start();
1501-
} else if (e.getComponent() == pauseButton) {
1502-
LOGGER.fine("Pause pressed");
1503-
timer.stop();
1504-
} else if (e.getComponent() == stopButton) {
1505-
LOGGER.fine("Stop pressed");
1506-
timeline.setValue(1);
1507-
timer.stop();
1508-
} else if (e.getComponent() == slowButton) {
1509-
DELAY = DELAY * 2;
1510-
timer.setDelay(DELAY);
1511-
LOGGER.fine("Slow pressed, delay=" + timer.getDelay());
1512-
} else if (e.getComponent() == fastButton) {
1513-
DELAY = DELAY / 2;
1514-
timer.setDelay(DELAY);
1515-
LOGGER.fine("Fast pressed, delay=" + timer.getDelay());
1516-
} else if (e.getComponent() == nextButton) {
1517-
try {
1518-
LOGGER.fine("Next pressed");
1519-
nextOrPrevGraph("next");
1520-
timer.stop();
1521-
} catch (Exception ex) {
1522-
LOGGER.log(Level.SEVERE, null, ex);
1523-
}
1524-
} else if (e.getComponent() == prevButton) {
1525-
try {
1526-
LOGGER.fine("Prev pressed");
1527-
nextOrPrevGraph("prev");
1528-
timer.stop();
1529-
} catch (Exception ex) {
1530-
LOGGER.log(Level.SEVERE, null, ex);
1531-
}
1532-
}
1533-
}
1534-
1535-
public void mouseReleased(MouseEvent e) {
1536-
//throw new UnsupportedOperationException("Not supported yet.");
1537-
}
1538-
1539-
public void mouseEntered(MouseEvent e) {
1540-
//throw new UnsupportedOperationException("Not supported yet.");
1456+
playButton = createTimelineButton("images/play.png", "Play", e -> {
1457+
LOGGER.fine("Play pressed");
1458+
timer.start();
1459+
});
1460+
pauseButton = createTimelineButton("images/pause.png", "Pause", e -> {
1461+
LOGGER.fine("Pause pressed");
1462+
timer.stop();
1463+
});
1464+
stopButton = createTimelineButton("images/stop.png", "Stop", e -> {
1465+
LOGGER.fine("Stop pressed");
1466+
timeline.setValue(1);
1467+
timer.stop();
1468+
});
1469+
prevButton = createTimelineButton("images/prev.png", "Previous important graph", e -> {
1470+
try {
1471+
LOGGER.fine("Prev pressed");
1472+
nextOrPrevGraph("prev");
1473+
timer.stop();
1474+
} catch (Exception ex) {
1475+
LOGGER.log(Level.SEVERE, null, ex);
15411476
}
1542-
1543-
public void mouseExited(MouseEvent e) {
1544-
//throw new UnsupportedOperationException("Not supported yet.");
1477+
});
1478+
nextButton = createTimelineButton("images/next.png", "Next important graph", e -> {
1479+
try {
1480+
LOGGER.fine("Next pressed");
1481+
nextOrPrevGraph("next");
1482+
timer.stop();
1483+
} catch (Exception ex) {
1484+
LOGGER.log(Level.SEVERE, null, ex);
15451485
}
1546-
};
1547-
playButton.addMouseListener(clickListener);
1548-
pauseButton.addMouseListener(clickListener);
1549-
stopButton.addMouseListener(clickListener);
1550-
slowButton.addMouseListener(clickListener);
1551-
fastButton.addMouseListener(clickListener);
1552-
prevButton.addMouseListener(clickListener);
1553-
nextButton.addMouseListener(clickListener);
1486+
});
1487+
slowButton = createTimelineButton("images/slow.png", "Slow down", e -> {
1488+
DELAY = DELAY * 2;
1489+
timer.setDelay(DELAY);
1490+
LOGGER.fine("Slow pressed, delay=" + timer.getDelay());
1491+
});
1492+
fastButton = createTimelineButton("images/fast.png", "Speed up", e -> {
1493+
DELAY = DELAY / 2;
1494+
timer.setDelay(DELAY);
1495+
LOGGER.fine("Fast pressed, delay=" + timer.getDelay());
1496+
});
15541497

15551498

15561499
Box box[] = new Box[1];
@@ -1578,6 +1521,27 @@ public void mouseExited(MouseEvent e) {
15781521
contentPanel.add(timeline);
15791522
}
15801523

1524+
/**
1525+
* Creates a timeline control button with an icon, tooltip, and action.
1526+
* Replaces the previous pattern of creating bare JButtons, manually
1527+
* setting icons, and routing all clicks through a single MouseListener
1528+
* with a component-identity if/else chain — which was fragile and
1529+
* contrary to Swing best practices (ActionListener is the correct
1530+
* abstraction for button clicks).
1531+
*
1532+
* @param iconPath path to the button icon image
1533+
* @param tooltip accessible tooltip text
1534+
* @param action the action to perform on click
1535+
* @return a configured JButton
1536+
*/
1537+
private JButton createTimelineButton(String iconPath, String tooltip,
1538+
ActionListener action) {
1539+
JButton button = new JButton(new ImageIcon(iconPath));
1540+
button.setToolTipText(tooltip);
1541+
button.addActionListener(action);
1542+
return button;
1543+
}
1544+
15811545
/**
15821546
* initialize the notes space
15831547
*/

0 commit comments

Comments
 (0)