/* (@)TextNoteFun.java */
/* Copyright 2009 Sebastian Haufe
* Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
[url]http://www.apache.org/licenses/LICENSE-2.0[/url]
* Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package com.ebenius;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.*;
import javax.swing.text.*;
public class TextNoteFun {
// -------------------------------------------------------------------------
// Editor kit, providing the view factory
// -------------------------------------------------------------------------
static class NoteSupportingEditorKit extends StyledEditorKit {
private static final long serialVersionUID = 1L;
private final ViewFactory viewFactory = new NoteMarkupViewFactory();
@Override
public ViewFactory getViewFactory() {
return viewFactory;
}
}
// -------------------------------------------------------------------------
// Label view, marking up text with notes
// -------------------------------------------------------------------------
static class NoteMarkupLabelView extends LabelView {
private static final Stroke stroke =
new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1,
new float[] { 5.f, 2.f }, 2.5f);
NoteMarkupLabelView(Element elem) {
super(elem);
}
private boolean hasNote() {
return null != getAttributes().getAttribute("textNote");
}
@Override
public String getToolTipText(float x, float y, Shape allocation) {
final Object text = getAttributes().getAttribute("textNote");
return text == null ? null : text.toString();
}
@Override
public void paint(Graphics g, Shape allocation) {
super.paint(g, allocation);
if (hasNote()) {
final Stroke oldStroke = ((Graphics2D) g).getStroke();
try {
((Graphics2D) g).setStroke(stroke);
g.setColor(Color.RED);
final Rectangle b = allocation.getBounds();
final int y = b.y + b.height - 2;
g.drawLine(b.x, y, b.x + b.width - 1, y);
} finally {
((Graphics2D) g).setStroke(oldStroke);
}
}
}
}
// -------------------------------------------------------------------------
// View Factory creating my own views instead of standard label views
// -------------------------------------------------------------------------
static class NoteMarkupViewFactory implements ViewFactory {
// The code has been copied from StyledEditorKit.StyledViewFactory, only
// LabelView has been replaced by NoteMarkupLabelView
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new NoteMarkupLabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
// default to text display
return new NoteMarkupLabelView(elem);
}
}
// -------------------------------------------------------------------------
// Program Entry Point
// -------------------------------------------------------------------------
/**
* Test main method.
*
* @param args ignored
*/
public static void main(String[] args) {
// create a document with random content
final StyledDocument document = new DefaultStyledDocument();
try {
document.insertString(0, createRandomString(1024, 78), null);
} catch (BadLocationException ex) {
// location 0 is not bad!
}
// create a text pane with my editor kit, document, size and tool tip
final JTextPane textPane = new JTextPane();
textPane.setEditorKit(new NoteSupportingEditorKit());
textPane.setStyledDocument(document);
textPane.setPreferredSize(new Dimension(400, 400));
ToolTipManager.sharedInstance().registerComponent(textPane);
// Action to add a note to the selected text
final AbstractAction addNoteAction = new AbstractAction("Add Note") {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
final int selStart = textPane.getSelectionStart();
final int selEnd = textPane.getSelectionEnd();
if (selStart < selEnd) {
final String noteText =
JOptionPane.showInputDialog("Type your note:");
if (noteText != null) {
final SimpleAttributeSet aset = new SimpleAttributeSet();
aset.addAttribute("textNote", noteText);
document.setCharacterAttributes(selStart, selEnd - selStart,
aset, true);
}
}
}
};
// standard GUI template
final JPanel bPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
bPanel.add(new JButton(addNoteAction));
final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
contentPane.add(new JScrollPane(textPane));
contentPane.add(bPanel, BorderLayout.SOUTH);
final JFrame f = new JFrame("Test Frame: TextNoteFun"); //$NON-NLS-1$
f.setContentPane(contentPane);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}
// -------------------------------------------------------------------------
// Create random string
// -------------------------------------------------------------------------
private static final char[] RANDOM_ALPHABET =
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ' };
private static String createRandomString(int len, int maxSpaceDistance) {
final char[] chars = new char[len];
final Random rnd = new Random();
int spaceDistance = 0;
for (int i = 0; i < chars.length; i++) {
final char c =
spaceDistance == maxSpaceDistance ? ' ' : RANDOM_ALPHABET[rnd
.nextInt(RANDOM_ALPHABET.length)];
if (c == ' ') {
spaceDistance = 0;
} else {
spaceDistance++;
}
chars[i] = c;
}
return new String(chars);
}
}