/* * The MIT License (MIT) * * Copyright (c) 2015 Camil Staps * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.camilstaps.mandelbrot; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Observable; import java.util.Observer; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; /** * The Textfields form a view and a controller for the FractalModel class, and * a controller for the Grid class * @author Camil Staps */ public class Textfields extends JPanel implements Observer { /** * The FractalModel to view and control */ private final FractalModel fractalModel; /** * The Grid to control */ private final Grid grid; /** * Initial values of the text fields */ private final String INITIAL_CENTER_X = "-0.46", INITIAL_CENTER_Y = "0", INITIAL_SCALE = "0.5"; /** * The components */ private final JTextField field_centerX = new JTextField(INITIAL_CENTER_X, 6); private final JTextField field_centerY = new JTextField(INITIAL_CENTER_Y, 6); private final JTextField field_scale = new JTextField(INITIAL_SCALE, 6); private final JButton button_redraw = new JButton("Redraw"); private final JButton button_reset = new JButton("Reset"); private final JCheckBox checkbox_multiple_swingworkers = new JCheckBox("Multiple SwingWorkers"); /** * Create a new instance * @param fractalModel * @param grid */ public Textfields(FractalModel fractalModel, Grid grid) { super(new BorderLayout()); this.fractalModel = fractalModel; this.grid = grid; fractalModel.addObserver(this); setupControls(); button_redraw.doClick(); } /** * Setup the swing components with their listeners */ private void setupControls() { JPanel panel = new JPanel(new GridLayout(9,1)); panel.add(new JLabel("Center x:")); panel.add(field_centerX); panel.add(new JLabel("Center y:")); panel.add(field_centerY); panel.add(new JLabel("Scale:")); panel.add(field_scale); button_redraw.addActionListener(new ActionListener() { /** * Update the FractalModel's bounds * @param ae */ @Override public void actionPerformed(ActionEvent ae) { if (ae.getActionCommand().equals("Redraw")) { fractalModel.setBounds(getStartX(), getEndX(), getStartY(), getEndY()); } } }); panel.add(button_redraw); button_reset.addActionListener(new ActionListener() { /** * Reset the textfields to their default values * @param ae */ @Override public void actionPerformed(ActionEvent ae) { field_centerX.setText(INITIAL_CENTER_X); field_centerY.setText(INITIAL_CENTER_Y); field_scale.setText(INITIAL_SCALE); button_redraw.doClick(); } }); panel.add(button_reset); checkbox_multiple_swingworkers.addActionListener(new ActionListener() { /** * Tell the Grid to use single or multiple SwingWorkers * @param ae */ @Override public void actionPerformed(ActionEvent ae) { grid.setUseMultipleSwingWorkers(checkbox_multiple_swingworkers.isSelected()); } }); panel.add(checkbox_multiple_swingworkers); add(panel, BorderLayout.NORTH); add(new JPanel(), BorderLayout.CENTER); } @Override public int getWidth() { return 200; } /** * Get the desired low bound on x of the model * @return */ protected double getStartX() { double width = 1 / Double.parseDouble(field_scale.getText()); double center = Double.parseDouble(field_centerX.getText()); return center - width / 2; } /** * Get the desired high bound on x of the model * @return */ protected double getEndX() { double width = 1 / Double.parseDouble(field_scale.getText()); double center = Double.parseDouble(field_centerX.getText()); return center + width / 2; } /** * Get the desired low bound on y of the model * @return */ protected double getStartY() { double height = 1 / Double.parseDouble(field_scale.getText()); double center = Double.parseDouble(field_centerY.getText()); return center - height / 2; } /** * Get the desired high bound on y of the model * @return */ protected double getEndY() { double height = 1 / Double.parseDouble(field_scale.getText()); double center = Double.parseDouble(field_centerY.getText()); return center + height / 2; } /** * Update the text fields based on the FractalModel's bounds * @param o * @param o1 */ @Override public final void update(Observable o, Object o1) { field_centerX.setText(Float.toString((float) ((fractalModel.getEndX() - fractalModel.getStartX()) / 2 + fractalModel.getStartX()))); field_centerY.setText(Float.toString((float) ((fractalModel.getEndY() - fractalModel.getStartY()) / 2 + fractalModel.getStartY()))); field_scale.setText(Float.toString((float) (1 / (fractalModel.getEndX() - fractalModel.getStartX())))); } }