ReplPane.java 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package kawa;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.awt.geom.*;
  5. import javax.swing.*;
  6. import javax.swing.text.*;
  7. import gnu.kawa.io.OutPort;
  8. import gnu.kawa.models.Viewable;
  9. import gnu.kawa.models.Picture;
  10. import gnu.kawa.swingviews.SwingDisplay;
  11. /** A JTextPane for a read-eval-print-loop. Also creates an
  12. * out and err PrintWriter so that you can redirect stdout/stderr to
  13. * these streams, using the System.setOut/setErr methods.
  14. *
  15. * @author Albert Ting
  16. * @author Per Bothner
  17. */
  18. public class ReplPane extends JTextPane
  19. implements KeyListener
  20. {
  21. ReplDocument document;
  22. /**
  23. * simple TextArea that always scrolls to the bottom. Also creates an
  24. * out and err PrintWriter so that you can redirect stdout/stderr to
  25. * these streams, using the System.setOut/setErr methods.
  26. */
  27. public ReplPane(ReplDocument document)
  28. {
  29. super(document);
  30. this.document = document;
  31. document.pane = this;
  32. document.paneCount++;
  33. addKeyListener(this);
  34. addFocusListener(document);
  35. setCaretPosition(document.outputMark);
  36. }
  37. @Override
  38. protected EditorKit createDefaultEditorKit() {
  39. return new ReplEditorKit(this);
  40. }
  41. /** This method is called by the toolkit when the component is removed.
  42. * Used as a hook to decrement ReplDocument's reference count,
  43. * and maybe close the document.
  44. */
  45. @Override
  46. public void removeNotify()
  47. {
  48. super.removeNotify();
  49. if (--document.paneCount == 0)
  50. document.close();
  51. }
  52. @Override
  53. public MutableAttributeSet getInputAttributes()
  54. {
  55. return ReplDocument.inputStyle;
  56. }
  57. public void keyPressed(KeyEvent e) {
  58. int code = e.getKeyCode();
  59. if (code == KeyEvent.VK_ENTER)
  60. {
  61. document.enter();
  62. e.consume();
  63. }
  64. }
  65. public void keyReleased(KeyEvent e) {
  66. }
  67. public void keyTyped(KeyEvent e) {
  68. }
  69. public OutPort getStdout() {
  70. return document.out_stream;
  71. }
  72. public OutPort getStderr() {
  73. return document.err_stream;
  74. }
  75. public static final String ViewableElementName = "Viewable";
  76. public static final String PictureElementName = "Picture";
  77. public static final Object ViewableAttribute =
  78. new String(ViewableElementName);
  79. public static final Object PictureAttribute =
  80. new String(PictureElementName);
  81. }
  82. class ReplEditorKit extends StyledEditorKit {
  83. ViewFactory styledFactory;
  84. ViewFactory factory;
  85. final ReplPane pane;
  86. public ReplEditorKit(final ReplPane pane)
  87. {
  88. this.pane = pane;
  89. styledFactory = super.getViewFactory();
  90. factory = new ViewFactory ()
  91. {
  92. public View create(Element elem)
  93. {
  94. String kind = elem.getName();
  95. if (kind == ReplPane.ViewableElementName)
  96. {
  97. return (new ComponentView(elem)
  98. {
  99. @Override
  100. protected Component createComponent()
  101. {
  102. AttributeSet attr = getElement().getAttributes();
  103. JPanel panel = new JPanel();
  104. Viewable v = (Viewable) attr.getAttribute(ReplPane.ViewableAttribute);
  105. Component comp;
  106. // A kludge: We create a panel, and then since all current
  107. // Viewables just create a Component and put it in the
  108. // panel, we get rid of the useless JPanel.
  109. v.makeView(SwingDisplay.getInstance(), panel);
  110. if (panel.getComponentCount() == 1)
  111. {
  112. comp = panel.getComponent(0);
  113. panel.removeAll();
  114. }
  115. else
  116. {
  117. panel.setBackground(pane.getBackground());
  118. comp = panel;
  119. }
  120. return comp;
  121. }
  122. });
  123. }
  124. else if (kind == ReplPane.PictureElementName)
  125. {
  126. AttributeSet attr = elem.getAttributes();
  127. return new PictureView(elem, (Picture) attr.getAttribute(ReplPane.PictureAttribute));
  128. }
  129. return styledFactory.create(elem);
  130. }
  131. };
  132. }
  133. @Override
  134. public ViewFactory getViewFactory ()
  135. {
  136. return factory;
  137. }
  138. }
  139. class PictureView extends View
  140. {
  141. Picture p;
  142. Rectangle2D bounds;
  143. public PictureView(Element elem, Picture picture)
  144. {
  145. super(elem);
  146. this.p = picture;
  147. this.bounds = picture.getBounds2D();
  148. }
  149. public void paint(Graphics g, Shape a)
  150. {
  151. Graphics2D g2 = (Graphics2D) g;
  152. Rectangle2D abounds = a.getBounds2D();
  153. AffineTransform saveTransform = g2.getTransform();
  154. Paint savePaint = g2.getPaint();
  155. try
  156. {
  157. g2.translate(abounds.getX()-bounds.getX(),
  158. abounds.getY()-bounds.getY());
  159. g2.setPaint(Color.BLACK); // FIXME
  160. p.paint(g2);
  161. }
  162. finally
  163. {
  164. g2.setTransform(saveTransform);
  165. g2.setPaint(savePaint);
  166. }
  167. }
  168. @Override
  169. public float getAlignment(int axis)
  170. {
  171. switch (axis)
  172. {
  173. case View.Y_AXIS:
  174. return 1;
  175. default:
  176. return super.getAlignment(axis);
  177. }
  178. }
  179. public float getPreferredSpan(int axis) {
  180. switch (axis) {
  181. case View.X_AXIS:
  182. return (float) bounds.getWidth();
  183. case View.Y_AXIS:
  184. return (float) bounds.getHeight();
  185. default:
  186. throw new IllegalArgumentException("Invalid axis: " + axis);
  187. }
  188. }
  189. public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
  190. int p0 = getStartOffset();
  191. int p1 = getEndOffset();
  192. if ((pos >= p0) && (pos <= p1)) {
  193. Rectangle r = a.getBounds();
  194. if (pos == p1) {
  195. r.x += r.width;
  196. }
  197. r.width = 0;
  198. return r;
  199. }
  200. throw new BadLocationException(pos + " not in range " + p0 + "," + p1, pos);
  201. }
  202. public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
  203. Rectangle alloc = (Rectangle) a;
  204. if (x < alloc.x + (alloc.width / 2)) {
  205. bias[0] = Position.Bias.Forward;
  206. return getStartOffset();
  207. }
  208. bias[0] = Position.Bias.Backward;
  209. return getEndOffset();
  210. }
  211. }