Download Concurrent.java, BlockingSwingThread.java

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
TDDD13/TDDC73 Lecture 3
Nov 11, 11 9:06
Concurrent.java
Page 1/1
Nov 11, 11 8:52
BlockingSwingThread.java
package lecture3.concurrent;
package lecture3.threads;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.Container;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.util.ArrayList;
java.util.List;
java.util.concurrent.TimeUnit;
import
import
import
import
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.SwingUtilities;
javax.swing.WindowConstants;
java.util.Map;
java.util.Queue;
java.util.concurrent.ConcurrentHashMap;
java.util.concurrent.ConcurrentLinkedQueue;
java.util.concurrent.Semaphore;
java.util.concurrent.locks.Lock;
java.util.concurrent.locks.ReentrantLock;
import javax.swing.SwingUtilities;
/**
* Examples of what you can do with concurrency in java. Does not run, and is
* not intended to.
*
* @author jernlas
*/
public class Concurrent {
Object
that;
volatile int
number = 0;
static Runnable runnable;
public static void main(String[] args) {
Lock lock = new ReentrantLock();
lock.lock();
// critical section
lock.unlock();
Semaphore sema = new Semaphore(3);
sema.acquireUninterruptibly();
// critical section
sema.release();
Page 1/2
import lab3.given.FemaleNamesSearchProvider;
import lecture1.painting.Counter;
/**
* <p>
* Creates a window that has a button and a counter. When the button is clicked
* the counter searches through a list of names and counts the number of a:s.
* </p>
* <p>
* The point here is to show what occurs when heavy processing is done on the
* swing thread. To be extra obviuos the list is searched a thousand times over.
* </p>
*
* @author jernlas
*/
public class BlockingSwingThread {
public static void main(String[] args) {
new BlockingSwingThread();
}
Map<String, String> map = new ConcurrentHashMap<String, String>();
map.put("key", "value");
Queue<String> queue = new ConcurrentLinkedQueue<String>();
queue.add("element");
SwingUtilities.isEventDispatchThread();
SwingUtilities.invokeLater(runnable);
try {
SwingUtilities.invokeAndWait(runnable);
} catch (Exception e) {
// ignore
}
}
public synchronized void critical() {
// critical section
}
public void partlyCritical() {
// do something
synchronized (this) {
// critical section
// synchronized on this instance
}
synchronized (that) {
// critical section
// synchronized on other object (that)
}
// do something
}
}
Friday November 11, 2011
public BlockingSwingThread() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
protected void createAndShowGUI() {
final JFrame frame = new JFrame("Blocking calls");
final JButton countButton = new JButton("Count ’a’s in the name list!");
final Counter counter = new Counter();
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(countButton, BorderLayout.NORTH);
pane.add(counter, BorderLayout.CENTER);
FemaleNamesSearchProvider provider = FemaleNamesSearchProvider
.getInstance();
final List<String> names = new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
names.addAll(provider.getData());
}
countButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter.setValue(0);
for (String name : names) {
for (int pos = 0; pos < name.length(); pos++) {
if (name.charAt(pos) == ’a’) {
counter.setValue(counter.getValue() + 1);
lecture3/concurrent/Concurrent.java, lecture3/threads/BlockingSwingThread.java
1/12
TDDD13/TDDC73 Lecture 3
BlockingSwingThread.java
Nov 11, 11 8:52
Page 2/2
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e1) {
// TODO Auto−generated catch block
e1.printStackTrace();
}
}
}
}
Nov 11, 11 8:52
NotBlockingSwingThread.java
Page 1/2
package lecture3.threads;
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.Container;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.util.ArrayList;
java.util.List;
java.util.concurrent.TimeUnit;
import
import
import
import
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.SwingUtilities;
javax.swing.WindowConstants;
}
});
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
import lab3.given.FemaleNamesSearchProvider;
import lecture1.painting.Counter;
/**
* <p>
* Creates a window that has a button and
* the counter searches through a list of
* </p>
* <p>
* This implementation is better than the
* during searching and the user will not
* though.
* </p>
*
* @author jernlas
*/
public class NotBlockingSwingThread {
a counter. When the button is clicked
names and counts the number of a:s.
blocking one, it can still be used
be agitated. It is still pretty ugly
public static void main(String[] args) {
new NotBlockingSwingThread();
}
public NotBlockingSwingThread() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
protected void createAndShowGUI() {
final JFrame frame = new JFrame("Blocking calls");
final JButton countButton = new JButton("Count ’a’s in the name list!");
final Counter counter = new Counter();
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(countButton, BorderLayout.NORTH);
pane.add(counter, BorderLayout.CENTER);
FemaleNamesSearchProvider provider = FemaleNamesSearchProvider
.getInstance();
final List<String> names = new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
names.addAll(provider.getData());
}
countButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter.setValue(0);
Runnable runnable = new Runnable() {
private volatile int value = 0;
Friday November 11, 2011
lecture3/threads/BlockingSwingThread.java, lecture3/threads/NotBlockingSwingThread.java
2/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:52
NotBlockingSwingThread.java
Page 2/2
@Override
public void run() {
for (String name : names) {
for (int pos = 0; pos < name.length(); pos++) {
if (name.charAt(pos) == ’a’) {
value++;
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e1) {
// TODO Auto−generated catch block
e1.printStackTrace();
}
}
}
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
counter.setValue(value);
}
});
}
};
new Thread(runnable).start();
}
});
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Nov 11, 11 8:52
SwingWorkerThread.java
Page 1/2
package lecture3.threads;
import
import
import
import
import
import
import
java.awt.BorderLayout;
java.awt.Container;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.util.ArrayList;
java.util.List;
java.util.concurrent.TimeUnit;
import
import
import
import
import
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.SwingUtilities;
javax.swing.SwingWorker;
javax.swing.WindowConstants;
import lab3.given.FemaleNamesSearchProvider;
import lecture1.painting.Counter;
/**
* <p>
* Creates a window that has a button and a counter. When the button is clicked
* the counter searches through a list of names and counts the number of a:s.
* </p>
* <p>
* This implementation is better than the non−blocking one, it will be updated
* continously and can be used during searching.
* </p>
*
* @author jernlas
*/
public class SwingWorkerThread {
/**
* Swing worker that counts all ’a’s in the list, updating the count as it
* goes along.
*
* @author jernlas
*/
private class CounterWorker extends SwingWorker<Integer, Integer> {
/**
* The main work, done in a separate thread.
*/
@Override
protected Integer doInBackground() throws Exception {
int value = 0;
for (String name : names) {
for (int pos = 0; pos < name.length(); pos++) {
if (name.charAt(pos) == ’a’) {
publish(value++);
TimeUnit.MILLISECONDS.sleep(1);
}
}
}
return value;
}
/**
* Called when doInBackground() completes. Executed in swing−thread.
*/
@Override
protected void done() {
try {
counter.setValue(get());
} catch (Exception e) {
// ignore
}
}
Friday November 11, 2011
lecture3/threads/NotBlockingSwingThread.java, lecture3/threads/SwingWorkerThread.java
3/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:52
SwingWorkerThread.java
Page 2/2
Nov 11, 11 8:52
SearchClient.java
Page 1/1
package lecture3.given;
/**
* Called after every few calls to publish(). Executed in swing−thread.
*
* @param updates The list of published values since last called.
*/
@Override
protected void process(List<Integer> updates) {
counter.setValue(updates.get(updates.size() − 1));
}
}
public static void main(String[] args) {
new SwingWorkerThread();
}
import java.util.List;
import lab3.given.SearchProvider;
/**
* This interface describes an asyncronous callback for searching lists of strin
gs.
* @author Johan Jernlås
* @version 1.0.0
* @see SearchProvider
*/
public interface SearchClient {
/**
* Callback from a search operation to report the search results.
* @param searchId The ID of the search this result pertains to
* @param response The matches returned for this search
*/
void searchResultUpdate(long searchId, List<String> response);
private final Counter counter = new Counter();
final List<String>
names
= new ArrayList<String>();
public SwingWorkerThread() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
protected void createAndShowGUI() {
final JFrame frame = new JFrame("Blocking calls");
final JButton countButton = new JButton("Count ’a’s in the name list!");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(countButton, BorderLayout.NORTH);
pane.add(counter, BorderLayout.CENTER);
FemaleNamesSearchProvider provider = FemaleNamesSearchProvider
.getInstance();
for (int i = 0; i < 1000; i++) {
names.addAll(provider.getData());
}
countButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new CounterWorker().execute();
}
});
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Friday November 11, 2011
lecture3/threads/SwingWorkerThread.java, lecture3/given/SearchClient.java
4/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:52
SearchProvider.java
Page 1/1
package lecture3.given;
import java.util.List;
import lab3.given.SearchClient;
/**
* This interface describes an asyncronous search service. It uses an internal
* thread pool for servicing several requests simultaneously. To use it the
* client must follow the following steps:
* <nl>
* <li>Call addObserver to register a SearchClient as an observer</li>
* <li>Call newAsyncSearch to run an new search</li>
* </nl>
* If completed properly the SearchProvider will return a response in a finite
* amount of time. It does not, however, guarantee that responses arrive in the
* same order as requests.
*
* @author Johan Jernlås
* @version 1.0.0
* @see SearchClient
*/
public interface SearchProvider {
/**
* Adds an observer that registers search results.
*
* @param t
*
The observer. May not be NULL or already registered.
*/
public void addObserver(SearchClient t);
/**
* A convenience method that dumps the whole dataset. It is only intended for
* testing and general sanity checks.
*
* @return The data that is searched by the newAsyncSearch method
*/
public List<String> getData();
/**
* Creates a new search for a number of matching strings. The response can
* not have more elements than the requested number, but it might have fewer.
*
* @param text
*
The text to search for
* @param number
*
The desired number of strings in the result.
* @return The ID for this search
*/
public long newAsyncSearch(String text, int number);
}
Nov 11, 11 8:54
ExampleWindow.java
Page 1/2
package se.jernlas.gemexample;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import se.jernlas.swing.gem.Gem;
import se.jernlas.swing.gem.types.TextType;
/**
* A simple example application meant to examplify how to use the Gem−component.
*
* @author jernlas
*/
class ExampleWindow extends JFrame {
/**
* Horizontal gap between components
*/
private static final int H_GAP
= 4;
/**
* Vertical gap between components
*/
private static final int V_GAP
= 4;
/**
* Serial version
*/
private static final long serialVersionUID
= 20101126L;
/**
* The TextField containing the text that is to be analyzed by the gem.
*/
private final JTextArea textToAnalyze
= new JTextArea();
/**
* A label prompting the user to start typing in <code>textToAnalyze</code>
*/
private final JLabel
textToAnalyzePrompt = new JLabel("Skriv något:");
/**
* The actual gem that gives the user feedback on his typing
*/
private final Gem
gemAnalyzer
= new Gem(textToAnalyze
.getDocument());
/**
* Creates a standard example frame with a simple
* textfield component that is analyzed by a gem.
*/
public ExampleWindow() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new FlowLayout(FlowLayout.LEFT, H_GAP, V_GAP));
add(textToAnalyzePrompt);
add(textToAnalyze);
textToAnalyze.setPreferredSize(new Dimension(100, 10*(int)textToAnalyze.ge
tPreferredSize().getHeight()));
add(gemAnalyzer);
gemAnalyzer.setPreferredSize(new Dimension(50, 50));
gemAnalyzer.addTextType(TextType.FORMAL_LETTER);
gemAnalyzer.addTextType(TextType.INFORMAL_LETTER);
Friday November 11, 2011
lecture3/given/SearchProvider.java, jernlas/gemexample/ExampleWindow.java
5/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
pack();
setVisible(true);
}
}
ExampleWindow.java
Page 2/2
Nov 11, 11 8:54
Main.java
Page 1/1
package se.jernlas.gemexample;
import javax.swing.SwingUtilities;
/**
* Convenience class for initializing the Gem−example application. Contains no
* logic except for starting the application.
*
* @author jernlas
*/
public class Main {
/**
* Entry point method, runs a Gem−example application.
*
* @param args
*
Declared pro forma, all arguments are ignored.
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ExampleWindow();
}
});
}
}
Friday November 11, 2011
jernlas/gemexample/ExampleWindow.java, jernlas/gemexample/Main.java
6/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
AnalyzableDocumentAdapter.java
Page 1/2
Nov 11, 11 8:54
package se.jernlas.swing.gem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import
import
import
import
AnalyzableDocumentAdapter.java
Page 2/2
@Override
public void addAnalyzer(TextAnalyzer a) {
analyzers.add(a);
}
/**
* Fires analyzeText for all TextAnalyzers observing this class. The list of
* observers is defensively copied before calling so that no errors will
* occur if the observer removes itself from the original list during
* execution of analyzeText().
*/
private void fireAnalyseTextEvent() {
List<TextAnalyzer> tmpList = Collections.unmodifiableList(analyzers);
for (TextAnalyzer textAnalyzer : tmpList) {
textAnalyzer.analyzeText(this);
}
javax.swing.event.DocumentEvent;
javax.swing.event.DocumentListener;
javax.swing.text.BadLocationException;
javax.swing.text.Document;
/**
* Adapter class, adapting a Document (the model for most text based swing
* components) to appear as an AnalyzableText.
*
* @author jernlas
* @see javax.swing.text.Document
*/
public class AnalyzableDocumentAdapter implements AnalyzableText {
}
@Override
public String getText() {
try {
return doc.getText(0, doc.getLength());
} catch (BadLocationException e) {
e.printStackTrace();
return "";
}
}
/**
* The backing Document that is used as a source for change events and text
* content. The document may not be changed once set by the constructor,
* since this would most likely result in unexpected behaviour.
*/
private final Document
doc;
/**
* A list of TextAnalyzers observing this AnalyzableText.
*/
private final List<TextAnalyzer> analyzers = new ArrayList<TextAnalyzer>();
/**
* Creates a new AnalyzableDocument, wrapping around the supplied Document
* object.
*
* @param doc
*
The document to use.
*/
public AnalyzableDocumentAdapter(Document doc) {
@Override
public void removeAnalyzer(TextAnalyzer a) {
analyzers.remove(a);
}
}
if (doc == null) {
throw new IllegalArgumentException("The document may not be NULL.");
}
this.doc = doc;
/* Use an anonymous subclass of DocumentListener to capture changes in the
* underlying Document and refire them as analyseText.
*
*/
doc.addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
fireAnalyseTextEvent();
}
@Override
public void insertUpdate(DocumentEvent e) {
fireAnalyseTextEvent();
}
@Override
public void removeUpdate(DocumentEvent e) {
fireAnalyseTextEvent();
}
});
}
Friday November 11, 2011
jernlas/swing/gem/AnalyzableDocumentAdapter.java
7/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
AnalyzableText.java
Page 1/1
package se.jernlas.swing.gem;
/**
*
* Any text that can be analyzed by a <code>TextAnalyzer</code>. This interface
* provides two vital functions:
* <ul>
* <li>A uniform interface for getting the text to analyze
* (<code>getText()</code>).</li>
* <li>Forces the client to accept TextAnalyzers, resembling the
* Observer in the well known Observable design pattern.</li>
* </ul>
*
* @author jernlas
*
*/
public interface AnalyzableText {
/**
* Adds a new TextAnalyzer
* @param analyzer The analyzer to add
*/
public void addAnalyzer(TextAnalyzer analyzer);
/**
* Removes a TextAnalyzer from the internal list of analyzers.
* This operation should allways be allowed (ie. all implementers must
* defensively copy the list before calling external code).
* @param analyzer The analyzer to remove
*/
public void removeAnalyzer(TextAnalyzer analyzer);
/**
* Gets the text that is to be used for any analysis by the TextAnalyzers.
* @return The text selected for analysis.
*/
public String getText();
Gem.java
Nov 11, 11 8:54
Page 1/5
package se.jernlas.swing.gem;
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import
import
import
import
import
import
import
import
import
import
javax.swing.BorderFactory;
javax.swing.BoxLayout;
javax.swing.JButton;
javax.swing.JComponent;
javax.swing.JPanel;
javax.swing.JWindow;
javax.swing.border.BevelBorder;
javax.swing.event.AncestorEvent;
javax.swing.event.AncestorListener;
javax.swing.text.Document;
import se.jernlas.swing.gem.types.TextType;
/**
* A swing−component that helps the user to create text−documents
* by analyzing what the user writes and presenting helpful suggestions.
*
* @author jernlas
*
*/
public class Gem extends JComponent implements TextAnalyzer, AncestorListener {
}
private static final long
serialVersionUID = −1449696234370220313L;
/**
* Last shown suggestions.
*/
private final Set<TextType> lastShownSuggestions = new HashSet<TextType>();
/**
* The types of document to try and identify.
*/
private final List<TextType> types
= new ArrayList<TextType>();
/**
* The window containing the list of suggestions
*/
private JWindow
tipWindow
= null;
/**
* Indicates whether there are tips to display
*/
private volatile boolean
hasTips
= false;
/**
* The color of the gem when there are no tips available
*/
private Color
inactiveColor
= Color.YELLOW;
/**
* The color of the gem when there are tips available
Friday November 11, 2011
jernlas/swing/gem/AnalyzableText.java, jernlas/swing/gem/Gem.java
8/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
*/
private Color
Gem.java
activeColor
Page 2/5
= Color.GREEN;
t.
* @param text The text to register as an analyzer for.
*/
public Gem(AnalyzableText text) {
this();
text.addAnalyzer(this);
}
/**
* Convenience constructor.
* Same as the one accepting a AnalyzableText parameter,
* only it accepts a Document, which is wrapped in an AnalyzableDocumentAdapt
@Override
public void addTextType(TextType t) {
types.add(t);
}
@Override
public void analyzeText(AnalyzableText text) {
final String currentText = text.getText();
List<TextType> matchingTypes = new LinkedList<TextType>();
for (TextType t : types) {
if (t.isThisType(currentText)) {
matchingTypes.add(t);
}
}
hasTips = (matchingTypes.size() > 0);
if (hasTips) {
displaySuggestions(matchingTypes);
} else {
hideSuggestions();
}
repaint();
}
boolean hasAll = lastShownSuggestions.containsAll(matchingTypes);
boolean noExtra = lastShownSuggestions.size() == matchingTypes.size();
// If displaying the same suggestions, don’t redraw.
if(hasAll && noExtra){
return;
} else {
lastShownSuggestions.clear();
lastShownSuggestions.addAll(matchingTypes);
}
// If there is already a window, dispose of it.
if (tipWindow != null) {
tipWindow.dispose();
}
// Create a new window and populate it with components generated
// from the selected TextTypes.
tipWindow = new JWindow(getFrame(null));
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
tipWindow.setContentPane(p);
p.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
for (TextType textType : matchingTypes) {
p.add(textType.getTip());
}
final JButton b = new JButton("No thanks...");
b.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
hideSuggestions();
}
});
p.add(b);
// Make the pop−up window behave as part of the component.
getFrame(null).addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent evt) {
if (tipWindow != null && !lastShownSuggestions.isEmpty()) {
tipWindow.setVisible(true);
}
}
@Override
public void ancestorAdded(AncestorEvent event) {
hideSuggestions();
}
@Override
public void ancestorMoved(AncestorEvent event) {
if (event.getSource() != tipWindow) {
placePopup();
}
}
Friday November 11, 2011
Page 3/5
/**
* Displays a list of Suggestions.
* @param matchingTypes The TextTypes that matches the text.
*/
private void displaySuggestions(Collection<TextType> matchingTypes) {
/**
* Creates a default gem and registers it as an analyzer for the supplied tex
* to make it analyzable.
* @param document The document to analyze.
*/
public Gem(Document document) {
this(new AnalyzableDocumentAdapter(document));
}
Gem.java
@Override
public void ancestorRemoved(AncestorEvent event) {
hideSuggestions();
}
/**
* Creates a default gem without associating it with a text.
* This can be done later by calling addAnalyzer() on the text.
*/
public Gem() {
addAncestorListener(this);
setOpaque(false);
}
er
Nov 11, 11 8:54
@Override
public void windowLostFocus(WindowEvent evt) {
if (tipWindow != null && lastShownSuggestions.isEmpty()) {
tipWindow.setVisible(false);
}
}
});
// Pack, show and position the pop−up window
jernlas/swing/gem/Gem.java
9/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
Gem.java
Page 4/5
tipWindow.pack();
tipWindow.toFront();
tipWindow.setVisible(true);
placePopup();
tipWindow.requestFocusInWindow();
Nov 11, 11 8:54
Gem.java
Page 5/5
public void removeTextType(TextType t) {
types.remove(t);
}
}
}
/**
* Recursively gets the root Frame.
* @param c The component to start from, if null this is used.
* @return The root Frame.
*/
private Frame getFrame(Component c) {
if (c == null) {
c = this;
}
if (c.getParent() instanceof Frame) {
return (Frame) c.getParent();
}
return getFrame(c.getParent());
}
/**
* Disables the pop−up suggestions.
*/
private void hideSuggestions() {
if (tipWindow != null) {
tipWindow.setVisible(false);
lastShownSuggestions.clear();
}
}
@Override
public void paint(Graphics g) {
if (isOpaque()) {
g.setColor(getBackground());
g.drawRect(0, 0, getWidth() − 1, getHeight() − 1);
}
if (hasTips) {
g.setColor(activeColor);
} else {
g.setColor(inactiveColor);
}
g.fillOval(0, 0, getWidth() − 1, getHeight() − 1);
g.setColor(getForeground());
g.drawOval(0, 0, getWidth() − 1, getHeight() − 1);
g.setColor(Color.WHITE);
g.fillOval((int)(0.7*getWidth()), (int)(0.25*getHeight()), (int)(0.15*(get
Width()−1)), (int)(0.15*(getHeight()−1)));
}
/**
* Correctly position the pop−up, depending on the position of the main compo
nent.
*/
private void placePopup() {
if (tipWindow != null) {
Point pt = this.getLocationOnScreen();
pt.translate(0, this.getHeight());
tipWindow.setLocation(pt);
}
}
@Override
Friday November 11, 2011
jernlas/swing/gem/Gem.java
10/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
TextAnalyzer.java
Page 1/1
Nov 11, 11 8:54
FormalLetterType.java
package se.jernlas.swing.gem;
package se.jernlas.swing.gem.types;
import se.jernlas.swing.gem.types.TextType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Pattern;
/**
* Analyzes an AnalyzableText in order to identify matching TextTypes.
*
* @author jernlas
*/
public interface TextAnalyzer {
/**
* Adds a TextType to the list of TextTypes to identify.
* @param type The TextType to add
*/
public void addTextType(TextType type);
Page 1/1
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
/**
* A formal letter TextType. Singleton. Not intended for direct use, accessed as
* a static field in TextType.
*
* @author jernlas
*/
class FormalLetterType extends TextType {
/**
* Perform the actual analysis.
* @param text The AnalyzableText to analyze
*/
public void analyzeText(AnalyzableText text);
/**
* The singleton instance
*/
private final static FormalLetterType instance = new FormalLetterType();
/**
* Removes a TextType from the list of identifiable types.
* @param type The TextType to remove.
*/
public void removeTextType(TextType type);
/**
* Prevent others from instantiating.
*/
private FormalLetterType() {
}
@Override
public JComponent getTip() {
final JButton b = new JButton(
"Det verkar som att du vill skriva ett formellt brev...");
b.addActionListener(new ActionListener() {
}
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(b,
"This is only an example application...");
}
});
return b;
}
@Override
public boolean isThisType(String text) {
return Pattern.matches("^Hej.*", text);
}
/**
* Gets the singleton instance.
*
* @return the instance.
*/
public static FormalLetterType getInstance() {
return instance;
}
}
Friday November 11, 2011
jernlas/swing/gem/TextAnalyzer.java, jernlas/swing/gem/types/FormalLetterType.java
11/12
TDDD13/TDDC73 Lecture 3
Nov 11, 11 8:54
InformalLetterType.java
Page 1/1
Nov 11, 11 8:54
TextType.java
package se.jernlas.swing.gem.types;
package se.jernlas.swing.gem.types;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Pattern;
import javax.swing.JComponent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
/**
* An informal letter TextType. Singleton. Not intended for direct use, accessed
* as a static field in TextType.
*
* @author jernlas
*/
class InformalLetterType extends TextType {
/**
* The singleton instance
*/
private final static InformalLetterType instance = new InformalLetterType();
/**
* A type of text that can be identified from a string and generate a
* Tip in the shape of a swing component.
*
* @author jernlas
*/
public abstract class TextType {
/**
* Identifies a formal letter
*/
public static final TextType FORMAL_LETTER = FormalLetterType.getInstance();
/**
* Identifies an informal letter
*/
public static final TextType INFORMAL_LETTER = InformalLetterType.getInstance
();
/**
* Prevent others from instantiating.
*/
private InformalLetterType() {
}
/**
* Generates a swing component that represents this tip.
* @return The component.
*/
public abstract JComponent getTip();
@Override
public JComponent getTip() {
final JButton b = new JButton(
"Det verkar som att du vill skriva ett informellt brev...");
b.addActionListener(new ActionListener() {
/**
* Check if the string matches this document type.
* @param text The text to check
* @return true if the text matches this type of document.
*/
public abstract boolean isThisType(String text);
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(b,
"This is only an example application...");
}
Page 1/1
}
});
return b;
}
@Override
public boolean isThisType(String text) {
return Pattern.matches("^Hejsan.*", text);
}
/**
* Gets the singleton instance.
*
* @return the instance.
*/
public static InformalLetterType getInstance() {
return instance;
}
}
Friday November 11, 2011
jernlas/swing/gem/types/InformalLetterType.java, jernlas/swing/gem/types/TextType.java
12/12
Related documents