Skip to content
Snippets Groups Projects
Commit 29172287 authored by Keiko Katsuragawa's avatar Keiko Katsuragawa
Browse files

add 3-0-MVC

parent 4e969ad9
No related branches found
No related tags found
No related merge requests found
Showing
with 1006 additions and 0 deletions
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME = "Main"
all:
@echo "Compiling..."
javac *.java
run: all
@echo "Running..."
java $(NAME)
clean:
rm -rf *.class
// HelloMVC: a simple MVC example
// the model is just a counter
// inspired by code by Joseph Mack, http://www.austintek.com/mvc/
/**
* Two views with integrated controllers. Uses java.util.Observ{er, able} instead
* of custom IView.
*/
import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame("HelloMVC4");
// create Model and initialize it
Model model = new Model();
// create View, tell it about model (and controller)
View view = new View(model);
// tell Model about View.
model.addObserver(view);
// create second view ...
View2 view2 = new View2(model);
model.addObserver(view2);
// let all the views know that they're connected to the model
model.notifyObservers();
// create a layout panel to hold the two views
JPanel p = new JPanel(new GridLayout(2,1));
frame.getContentPane().add(p);
// add views (each view is a JPanel)
p.add(view);
p.add(view2);
// setup window
frame.setPreferredSize(new Dimension(300,300));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import java.util.Observable;
// HelloMVC: a simple MVC example
// the model is just a counter
// inspired by code by Joseph Mack, http://www.austintek.com/mvc/
public class Model extends Observable {
// the data in the model, just a counter
private int counter;
Model() {
setChanged();
}
public int getCounterValue() {
return counter;
}
public void incrementCounter() {
if (counter < 5) {
counter++;
System.out.println("Model: increment counter to " + counter);
setChanged();
notifyObservers();
}
}
}
// HelloMVC: a simple MVC example
// the model is just a counter
// inspired by code by Joseph Mack, http://www.austintek.com/mvc/
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;
import java.util.Observable;
import java.util.Observer;
class View extends JPanel implements Observer {
// the view's main user interface
private JButton button;
// the model that this view is showing
private Model model;
View(Model model) {
// create the view UI
button = new JButton("?");
button.setMaximumSize(new Dimension(100, 50));
button.setPreferredSize(new Dimension(100, 50));
// a GridBagLayout with default constraints centres
// the widget in the window
this.setLayout(new GridBagLayout());
this.add(button, new GridBagConstraints());
// set the model
this.model = model;
// setup the event to go to the "controller"
// (this anonymous class is essentially the controller)
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.incrementCounter();
}
});
}
// Observer interface
@Override
public void update(Observable arg0, Object arg1) {
System.out.println("View: update");
button.setText(Integer.toString(model.getCounterValue()));
}
}
// HelloMVC: a simple MVC example
// the model is just a counter
// inspired by code by Joseph Mack, http://www.austintek.com/mvc/
import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.Color;
import java.awt.event.*;
import java.util.*;
class View2 extends JPanel implements Observer {
// the model that this view is showing
private Model model;
private JLabel label = new JLabel();
View2(Model model) {
// create UI
setBackground(Color.WHITE);
setLayout(new FlowLayout(FlowLayout.LEFT));
this.add(this.label);
// set the model
this.model = model;
// setup the event to go to the "controller"
// (this anonymous class is essentially the controller)
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
model.incrementCounter();
}
});
}
// Observer interface
@Override
public void update(Observable o, Object arg) {
System.out.println("View2: updateView");
// just displays an 'X' for each counter value
String s = "";
for (int i=0; i<this.model.getCounterValue(); i++) s = s + "X";
this.label.setText(s);
}
}
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME = "Main"
all:
@echo "Compiling..."
javac *.java
run: all
@echo "Running..."
java $(NAME)
clean:
rm -rf *.class
import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.*;
public class Main extends JPanel {
public static void main(String[] args){
JFrame frame = new JFrame("NoMvc");
frame.getContentPane().add(new Main());
frame.setPreferredSize(new Dimension(300,300));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
int counter = 0;
void increaseCounter() {
if (counter < 5) {
counter++;
String s = Integer.toString(counter);
button.setText(s);
// just displays an 'X' for each counter value
s = "";
for (int i = 0; i< counter; i++) s = s + "X";
label.setText(s);
}
}
JButton button;
JLabel label;
public Main() {
this.setLayout(new GridLayout(2,1));
JPanel topPanel = new JPanel();
button = new JButton("?");
button.setMaximumSize(new Dimension(100, 50));
button.setPreferredSize(new Dimension(100, 50));
topPanel.setLayout(new GridBagLayout());
topPanel.add(button, new GridBagConstraints());
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseCounter();
}
});
this.add(topPanel);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
label = new JLabel("");
bottomPanel.add(label);
bottomPanel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
increaseCounter();
}
});
this.add(bottomPanel);
}
}
\ No newline at end of file
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME = "Main"
all:
@echo "Compiling..."
javac *.java
run: all
@echo "Running..."
java $(NAME)
clean:
rm -rf *.class
# MVC Code Demos
## Hello MVC Demos
Simple MVC examples using an incremental counter model. Each directory has a make file with MVC classes. These demos were inspired by Joseph Mack: http://www.austintek.com/mvc/
* `nomvc/` same functionality as MVC demos, but not using MVC
* `hellomvc1/` separate view and controller classes, only 1 view
* `hellomvc2/` separate view and controller classes, multiple views
* `hellomvc3/` controller combined into view, multiple views
* `hellomvc3b/` controller combined into view, views use modelListeners
* `hellomvc4/` using Java's Observer interface and Observable base class
## Triangle Demos
These are more complex MVC examples using a right-angle triangle model
All use the same "right-angle triangle" Model:
* `model/TriangleModel.java` the model used in every example
* `model/IView.java` the view interface used in every example
There are different Views and Controllers:
* `SimpleTextView.java` a very limited but simple view
* `TextView.java` a text view with correct controller updates and protected field
* `SliderView` uses slider widgets to adjust side lengths
* `SpinnerView` uses spinner widgets to adjust side lengths
* `GraphicalView` adjust side length using direct manipulation of a picture of the triangle
These views are combined in different ways. Set makefile NAME to one of the following startup classes to run:
* `Main1.java` SimpleTextView only
* `Main2.java` TextView only
* `Main3.java` multiple views at once
* `Main4.java` GraphicalView demo
* `Main5.java` multiple views using a tab
These demos also show how to use packages to organize code and they use the `FormLayout` custom layout manager.
\ No newline at end of file
import javax.swing.JFrame;
import model.TriangleModel;
public class Main1 {
public static void main(String[] args) {
TriangleModel model = new TriangleModel();
view.SimpleTextView view = new view.SimpleTextView(model);
JFrame frame = new JFrame("Triangle Main1");
frame.getContentPane().add(view);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import javax.swing.JFrame;
import model.TriangleModel;
public class Main2 {
public static void main(String[] args) {
model.TriangleModel model = new TriangleModel();
view.TextView view = new view.TextView(model);
JFrame frame = new JFrame("Triangle Main2");
frame.getContentPane().add(view);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import javax.swing.JFrame;
import model.TriangleModel;
import view.*;
import java.awt.GridLayout;
public class Main3 {
public static void main(String[] args) {
model.TriangleModel model = new TriangleModel();
TextView vText = new TextView(model);
ButtonView vButton = new ButtonView(model);
SliderView vSlider = new SliderView(model);
SpinnerView vSpinner = new SpinnerView(model);
JFrame frame = new JFrame("Triangle Main3");
frame.getContentPane().setLayout(new GridLayout(2, 2));
frame.getContentPane().add(vText);
frame.getContentPane().add(vButton);
frame.getContentPane().add(vSlider);
frame.getContentPane().add(vSpinner);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import javax.swing.JFrame;
import model.TriangleModel;
import view.*;
import java.awt.GridLayout;
public class Main4 {
public static void main(String[] args) {
model.TriangleModel model = new TriangleModel();
GraphicalView vGraphical = new GraphicalView(model);
JFrame frame = new JFrame("Triangle Main4");
frame.getContentPane().add(vGraphical);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
import javax.swing.*;
import model.TriangleModel;
import view.*;
import java.awt.GridLayout;
public class Main5 {
public static void main(String[] args) {
model.TriangleModel model = new TriangleModel();
GraphicalView vGraphical = new GraphicalView(model);
TextView vText = new TextView(model);
JFrame frame = new JFrame("Triangle Main5");
JTabbedPane tabs = new JTabbedPane();
tabs.add("Text View", vText);
tabs.add("Graphical View", vGraphical);
frame.getContentPane().add(tabs);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
# super simple makefile
# call it using 'make NAME=name_of_code_file_without_extension'
# (assumes a .java extension)
NAME = "Main1"
all:
# (a bit of a hack to compile everything each time ...)
@echo "Compiling..."
javac *.java model/*.java view/*.java
run: all
@echo "Running..."
java $(NAME)
clean:
rm -rf *.class
rm -rf view/*.class
rm -rf model/*.class
package model;
public interface IView {
/**
* This method is called by the model whenever it changes state.
*/
public void updateView();
}
package model;
// Note! Nothing from the view package is imported here.
import java.util.ArrayList;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoableEdit;
public class TriangleModel {
/* A list of the model's views. */
private ArrayList<IView> views = new ArrayList<IView>();
// Limit the size of the triangle.
public static final double MAX_SIDE = 100.0;
public static final double MAX_HYPO =
Math.sqrt(MAX_SIDE * MAX_SIDE + MAX_SIDE * MAX_SIDE);
private double base = 50.0; // length of the base
private double height = 50.0; // height of the triangle
public TriangleModel() { }
/** Set the base to a new value. Must be between 0 and MAX_BASE. */
public void setBase(double theBase) {
double tmp = Math.max(0, theBase);
this.base = Math.min(tmp, MAX_SIDE);
this.updateAllViews(); // update Views!
}
/** Set the height to a new value. Must be between 0 and MAX_HEIGHT. */
public void setHeight(double theHeight) {
this.height = Math.min(Math.max(0, theHeight), MAX_SIDE);
this.updateAllViews(); // update Views!
}
/** Set both the base and the height to new values. */
public void setValues(double theBase, double theHeight) {
this.base = Math.min(Math.max(0, theBase), MAX_SIDE);
this.height = Math.min(Math.max(0, theHeight), MAX_SIDE);
this.updateAllViews(); // update Views!
}
/** Get the length of this triangle's base. */
public double getBase() {
return this.base;
}
/** Get this triangle's height. */
public double getHeight() {
return this.height;
}
/** Get the length of this triangle's hypotenuse. */
public double getHypotenuse() {
return Math.sqrt(this.base * this.base + this.height * this.height);
}
/** Add a new view of this triangle. */
public void addView(IView view) {
this.views.add(view);
view.updateView(); // update Views!
}
/** Remove a view from this triangle. */
public void removeView(IView view) {
this.views.remove(view);
}
/** Update all the views that are viewing this triangle. */
private void updateAllViews() {
for (IView view : this.views) {
view.updateView();
}
}
}
package view;
import model.*;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.event.*;
import java.text.NumberFormat;
import java.awt.GridLayout;
public class ButtonView extends JPanel {
private TriangleModel model;
private JLabel base = new JLabel("0.0");
private JLabel height = new JLabel("0.0");
private JLabel hypo = new JLabel("0.0");
private JButton baseUp = new JButton("+");
private JButton baseDn = new JButton("-");
private JButton heightUp = new JButton("+");
private JButton heightDn = new JButton("-");
private NumberFormat formatter = NumberFormat.getNumberInstance();
private static final int MAX_FRACTION_DIGITS = 5;
public ButtonView(TriangleModel aModel) {
super();
this.model = aModel;
this.layoutView();
this.registerControllers();
this.model.addView(new IView() {
public void updateView() {
base.setText(formatter.format(model.getBase()));
height.setText(formatter.format(model.getHeight()));
hypo.setText(formatter.format(model.getHypotenuse()));
// Updating the view includes enabling/disabling components!
baseUp.setEnabled(model.getBase() < TriangleModel.MAX_SIDE);
baseDn.setEnabled(model.getBase() > 1);
heightUp.setEnabled(model.getHeight() < TriangleModel.MAX_SIDE);
heightDn.setEnabled(model.getHeight() > 1);
}
});
}
private void layoutView() {
this.setLayout(new FormLayout());
this.add(new JLabel("Base:"));
this.add(this.groupComponents(this.baseUp, this.baseDn, this.base));
this.add(new JLabel("Height:"));
this.add(this
.groupComponents(this.heightUp, this.heightDn, this.height));
this.add(new JLabel("Hypotenuse:"));
this.add(this.hypo);
Dimension d = this.hypo.getPreferredSize();
d.width = 80;
this.base.setPreferredSize(d);
this.height.setPreferredSize(d);
this.hypo.setPreferredSize(d);
this.formatter.setMaximumFractionDigits(MAX_FRACTION_DIGITS);
}
private Box groupComponents(JButton up, JButton dn, JLabel label) {
Box group = Box.createHorizontalBox();
group.add(up);
group.add(dn);
group.add(label);
Dimension d = up.getPreferredSize();
d.width = Math.max(up.getPreferredSize().width,
dn.getPreferredSize().width);
up.setPreferredSize(d);
dn.setPreferredSize(d);
return group;
}
private void registerControllers() {
this.baseUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
model.setBase(model.getBase() + 1);
}
});
this.baseDn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
model.setBase(model.getBase() - 1);
}
});
this.heightUp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
model.setHeight(model.getHeight() + 1);
}
});
this.heightDn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
model.setHeight(model.getHeight() - 1);
}
});
}
}
package view;
import java.awt.LayoutManager;
import java.awt.Insets;
import java.util.ArrayList;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
/**
* A layout manager that arranges components in a double column. In most cases
* the left column will hold a label and the right column will hold a component
* the user can manipulate. Preferred component sizes are respected as much as
* possible. Components in the left column are right justified; components in
* the right column are left justified. <img src="doc-files/FormLayout.gif">
*
* @author Byron Weber Becker
*/
public class FormLayout implements LayoutManager {
private int hGap = 6;
private int vGap = 4;
/** Construct a new FormLayout object. */
public FormLayout() {
super();
}
/**
* Construct a new FormLayout object.
*
* @param hGap
* the number of hortizontal pixels between components
* @param vGap
* the number of vertical pixels between components
*/
public FormLayout(int hGap, int vGap) {
super();
this.hGap = hGap;
this.vGap = vGap;
}
/**
* Adds the specified component with the specified name to the layout.
*
* @param name
* the component name
* @param comp
* the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
}
/**
* Removes the specified component from the layout.
*
* @param comp
* the component to be removed
*/
public void removeLayoutComponent(Component comp) {
}
/**
* Calculates the preferred size dimensions for the specified panel given
* the components in the specified parent container.
*
* @param parent
* the component to be laid out
*
* @see #minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
ColDims cd = colDims(parent, true);
Insets insets = parent.getInsets();
Dimension d = new Dimension(cd.left + cd.right + insets.left
+ insets.right, cd.height + insets.top + insets.bottom);
return d;
}
}
/*
* Precondition: the caller has gotten the treelock. preferred = true for
* preferred sizes; false for minimum sizes
*/
private ColDims colDims(Container parent, boolean preferred) {
ColDims cd = new ColDims();
int nComponents = parent.getComponentCount();
// left column
for (int i = 1; i < nComponents; i += 2) {
Component left = parent.getComponent(i - 1);
Component right = parent.getComponent(i);
Dimension dLeft;
Dimension dRight;
if (preferred) {
dLeft = left.getPreferredSize();
dRight = right.getPreferredSize();
} else {
dLeft = left.getMinimumSize();
dRight = right.getMinimumSize();
}
cd.left = (int) Math.max(cd.left, dLeft.width);
cd.right = (int) Math.max(cd.right, dRight.width);
cd.height += (int) Math.max(dLeft.height, dRight.height);
cd.height += this.vGap;
}
if (nComponents % 2 == 1) { // odd number of components -- get the last
// one on the left
Component left = parent.getComponent(nComponents - 1);
Dimension dLeft;
if (preferred) {
dLeft = left.getPreferredSize();
} else {
dLeft = left.getMinimumSize();
}
cd.left = (int) Math.max(cd.left, dLeft.width);
cd.height += dLeft.height + this.vGap;
}
cd.left += this.hGap / 2;
cd.right += this.hGap / 2;
return cd;
}
/**
* Calculates the minimum size dimensions for the specified panel given the
* components in the specified parent container.
*
* @param parent
* the component to be laid out
* @see #preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent) {
synchronized (parent.getTreeLock()) {
ColDims cd = colDims(parent, false);
Insets insets = parent.getInsets();
Dimension d = new Dimension(cd.left + cd.right + insets.left
+ insets.right, cd.height + insets.top + insets.bottom);
return d;
}
}
/**
* Lays out the container in the specified panel.
*
* @param parent
* the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
synchronized (parent.getTreeLock()) {
ColDims cd = this.colDims(parent, true);
int desiredWidth = cd.left + cd.right + insets.left + insets.right;
double widthScale = Math.min(1.0, parent.getWidth()
/ (double) desiredWidth);
double heightScale = Math.min(1.0, parent.getHeight()
/ (double) cd.height);
double scale = Math.min(widthScale, heightScale);
// System.out.println("FormLayout.layoutContainer: widthScale = " +
// widthScale + "; heightScale = " + heightScale);
int midPt = (int) (((cd.left + insets.left + this.hGap) / (double) (cd.left
+ cd.right + insets.left + insets.right + hGap)) * parent
.getWidth());
int top = insets.top + this.vGap;
int nComponents = parent.getComponentCount();
for (int i = 1; i < nComponents; i += 2) {
Component left = parent.getComponent(i - 1);
Component right = parent.getComponent(i);
Dimension lDim = left.getPreferredSize();
Dimension rDim = right.getPreferredSize();
int rowHeight = (int) (Math.max(lDim.height, rDim.height) * heightScale);
// scale left side, if necessary; then position
if (lDim.width > desiredWidth || lDim.height > rowHeight) {
lDim.width = (int) (lDim.width * scale);
lDim.height = (int) (lDim.height * scale);
}
left.setBounds((midPt - lDim.width - this.hGap / 2), top,
lDim.width, lDim.height);
// scale left side, if necessary; then position
if (rDim.width > desiredWidth || rDim.height > rowHeight) {
rDim.width = (int) (rDim.width * scale);
rDim.height = (int) (rDim.height * scale);
}
right.setBounds(midPt + this.hGap / 2, top, rDim.width,
rDim.height);
top = top + rowHeight + this.vGap;
}
if (nComponents % 2 == 1) { // odd number of components -- get the
// last one on the left
Component left = parent.getComponent(nComponents - 1);
Dimension lDim = left.getPreferredSize();
lDim.width = (int) (lDim.width * scale);
lDim.height = (int) (lDim.height * scale);
left.setBounds((midPt - lDim.width - this.hGap / 2), top,
lDim.width, lDim.height);
}
}
}
private static class ColDims {
int left = 0;
int right = 0;
int height = 0;
}
}
package view;
import model.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
/**
* A view of a right triangle that displays the triangle graphically and allows
* the user to change the size by dragging the image with a mouse.
*/
public class GraphicalView extends JComponent {
private TriangleModel model;
private double scale = 1.0; // how much should the triangle be scaled?
private int handleSize = 5; // size of selectable square for dragging
// To format numbers consistently in the text fields.
private static final NumberFormat formatter = NumberFormat
.getNumberInstance();
public GraphicalView(TriangleModel aModel) {
super();
this.model = aModel;
this.layoutView();
this.registerControllers();
this.model.addView(new IView() {
/** The model changed. Ask the system to repaint the triangle. */
public void updateView() {
repaint();
}
});
}
/** How should it look on the screen? */
private void layoutView() {
this.setPreferredSize(new Dimension(200, 200));
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
}
/** Register event Controllers for mouse clicks and motion. */
private void registerControllers() {
MouseInputListener mil = new MController();
this.addMouseListener(mil);
this.addMouseMotionListener(mil);
}
/** Paint the triangle with "handle" for resizing */
public void paintComponent(Graphics g) {
super.paintComponent(g);
Insets insets = this.getInsets();
this.scale = Math.min((this.getWidth() - insets.left - insets.right)
/ (TriangleModel.MAX_SIDE + 2),
(this.getHeight() - insets.top - insets.bottom)
/ (TriangleModel.MAX_SIDE + 2));
double base = this.model.getBase();
double height = this.model.getHeight();
double hypo = this.model.getHypotenuse();
int left = this.toX(0);
int right = this.toX(base);
int bottom = this.toY(0);
int top = this.toY(height);
// Draw the triangle
g.setColor(Color.black);
g.drawLine(left, bottom, right, bottom);
g.drawLine(right, bottom, right, top);
g.drawLine(left, bottom, right, top);
// Label the edges
g.drawString(formatter.format(base), left + (right - left) / 2, bottom);
g.drawString(formatter.format(height), right, top + (bottom - top) / 2);
g.drawString(formatter.format(hypo), left + (right - left) / 2 - 15,
top + (bottom - top) / 2 - 15);
/** Draw "handles" for resizing the triangle. */
// g.fillRect(right - handleSize, bottom - handleSize,
// handleSize * 2, handleSize * 2);
g.fillRect(right - handleSize, top - handleSize,
handleSize * 2, handleSize * 2);
}
/** Convert from the model's X coordinate to the component's X coordinate. */
protected int toX(double modelX) {
return (int) (modelX * this.scale) + this.getInsets().left;
}
/** Convert from the model's Y coordinate to the component's Y coordinate. */
protected int toY(double modelY) {
return this.getHeight() - (int) (modelY * this.scale) - 1
- this.getInsets().bottom;
}
/** Convert from the component's X coordinate to the model's X coordinate. */
protected double fromX(int x) {
return (x - this.getInsets().left) / this.scale;
}
/** Convert from the component's Y coordinate to the model's Y coordinate. */
protected double fromY(int y) {
return (this.getHeight() - 1 - this.getInsets().bottom - y)
/ this.scale;
}
/**
* Does the given point (screen coordinates) lie on the upper right corner
* of the triangle?
*/
private boolean onTopCorner(int x, int y) {
return Math.abs(fromX(x) - this.model.getBase()) < handleSize
&& Math.abs(fromY(y) - this.model.getHeight()) < handleSize;
}
private class MController extends MouseInputAdapter {
private boolean selected = false; // did the user select the triangle to
// resize it?
public void mousePressed(MouseEvent e) {
selected = onTopCorner(e.getX(), e.getY());
}
// public void mouseReleased(MouseEvent e) {
// selected = onTopCorner(e.getX(), e.getY());
// }
/** The user is dragging the mouse. Resize appropriately. */
public void mouseDragged(MouseEvent e) {
if (selected) {
model.setBase(fromX(e.getX()));
model.setHeight(fromY(e.getY()));
}
}
} // MController
} // GraphicalView
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment