package expressionConsole;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
/**
* The view of the Model View Controller paradigm for the expression console.
* This view is a graphical text representation of the ExpressionConsoleModel.
*
* @author Curran Kelleher
*
*/
public class ExpressionConsoleView extends JScrollPane implements Observer,
AdjustmentListener {
private static final long serialVersionUID = 6185291782620102768L;
/**
* A reference to the singleton model. (so we don't need call getInstance()
* many times)
*/
ExpressionConsoleModel model = ExpressionConsoleModel.getInstance();
/**
* The internal model for the text. It is used to specify the style of
* specific text segments.
*/
StyledDocument document;
/**
* The JTextPanel which displays the entry history as text.
*/
JTextPane textPane;
/**
* A counter used to keep track of the length of the history which is
* currently displayed.
*/
int displayedHistorySize = 0;
/**
* A flag used to determine whether or not the scroll bar listener should
* scroll to the bottom in response to scroll bar property changes. It
* should only do this when the change comes from the program, not the user,
* so that's when this flag is set to true.
*/
boolean scrollBarAdjustmentWasFromTheUser = true;
/**
* Upon construction, the colors and styles of the textPane are set up.
*
*/
public ExpressionConsoleView() {
// create the text pane
textPane = new JTextPane();
textPane.setEditable(false);
// add it to this JScrollPane
setViewportView(textPane);
// set the background and foreground (default for text) colors
textPane.setBackground(Color.black);
textPane.setForeground(Color.orange);
// set the font
textPane.setFont(Font.decode("Monospaced-PLAIN-13"));
// add the INPUT style
Style style = textPane.addStyle(ExpressionConsoleHistoryEntry.INPUT
+ "", null);
StyleConstants.setForeground(style, Color.orange);
// add the CONSOLE_RESPONSE_SUCCESS style
style = textPane.addStyle(
ExpressionConsoleHistoryEntry.CONSOLE_RESPONSE_SUCCESS + "",
null);
StyleConstants.setForeground(style, Color.green);
// add the CONSOLE_RESPONSE_ERROR style
style = textPane
.addStyle(ExpressionConsoleHistoryEntry.CONSOLE_RESPONSE_ERROR
+ "", null);
StyleConstants.setForeground(style, Color.red);
StyleConstants.setBold(style, true);
// add the MESSAGE style
style = textPane.addStyle(ExpressionConsoleHistoryEntry.MESSAGE + "",
null);
StyleConstants.setForeground(style, Color.CYAN);
// get a reference to the internal document for later re-use
document = textPane.getStyledDocument();
// add a listener to the scrollbar which will ensure the desired
// behavior that the view is always scrolled to the very bottom every
// time an update is made.
getVerticalScrollBar().addAdjustmentListener(this);
// initialize the display to show the current contents of the model by
// sending an artificial update noficaiton
update(null, null);
}
/**
* Responds to scroll bar changes
*/
public void adjustmentValueChanged(AdjustmentEvent e) {
if (!scrollBarAdjustmentWasFromTheUser)
e.getAdjustable().setValue(e.getAdjustable().getMaximum());
scrollBarAdjustmentWasFromTheUser = true;
}
/**
* Responds to notifications from the model when it has changed.
*/
public void update(Observable o, Object arg) {
// extract the text from the model and display it
List<ExpressionConsoleHistoryEntry> historyList = model
.getExpressionHistory().getExpressionList();
int actualHistorySize = historyList.size();
// set the flag so that the scroll bar listener scrolls down to the
// bottom
scrollBarAdjustmentWasFromTheUser = false;
try {
for (int i = displayedHistorySize; i < actualHistorySize; i++) {
ExpressionConsoleHistoryEntry currentEntry = historyList.get(i);
// stylize the text (remember that upon construction, the styles
// map was coordinated to String representations of the type
// codes.)
document.insertString(document.getLength(), currentEntry
.getString()
+ "\n", textPane.getStyle(currentEntry.getType() + ""));
}
// catch the exeption which could be thrown from
// document.insertString()
} catch (BadLocationException e) {
e.printStackTrace();
}
// update displayedHistorySize for next time
displayedHistorySize = actualHistorySize;
}
}