1. /*
  2. * @(#)HiddenTagView.java 1.6 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text.html;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.io.*;
  11. import java.net.MalformedURLException;
  12. import java.net.URL;
  13. import javax.swing.text.*;
  14. import javax.swing.*;
  15. import javax.swing.border.*;
  16. import javax.swing.event.*;
  17. import java.util.*;
  18. /**
  19. * HiddenTagView subclasses EditableView to contain a JTextField showing
  20. * the element name. When the textfield is edited the element name is
  21. * reset. As this inherits from EditableView if the JTextComponent is
  22. * not editable, the textfield will not be visible.
  23. *
  24. * @author Scott Violet
  25. * @version 1.6, 11/29/01
  26. */
  27. class HiddenTagView extends EditableView implements DocumentListener {
  28. HiddenTagView(Element e) {
  29. super(e);
  30. yAlign = 1;
  31. }
  32. protected Component createComponent() {
  33. JTextField tf = new JTextField(getElement().getName());
  34. Document doc = getDocument();
  35. Font font;
  36. if (doc instanceof StyledDocument) {
  37. font = ((StyledDocument)doc).getFont(getAttributes());
  38. tf.setFont(font);
  39. }
  40. else {
  41. font = tf.getFont();
  42. }
  43. tf.getDocument().addDocumentListener(this);
  44. updateYAlign(font);
  45. // Create a panel to wrap the textfield so that the textfields
  46. // laf border shows through.
  47. JPanel panel = new JPanel(new BorderLayout());
  48. panel.setBackground(null);
  49. if (isEndTag()) {
  50. panel.setBorder(EndBorder);
  51. }
  52. else {
  53. panel.setBorder(StartBorder);
  54. }
  55. panel.add(tf);
  56. return panel;
  57. }
  58. public float getAlignment(int axis) {
  59. if (axis == View.Y_AXIS) {
  60. return yAlign;
  61. }
  62. return 0.5f;
  63. }
  64. public float getMinimumSpan(int axis) {
  65. if (axis == View.X_AXIS && isVisible()) {
  66. // Default to preferred.
  67. return Math.max(30, super.getPreferredSpan(axis));
  68. }
  69. return super.getMinimumSpan(axis);
  70. }
  71. public float getPreferredSpan(int axis) {
  72. if (axis == View.X_AXIS && isVisible()) {
  73. return Math.max(30, super.getPreferredSpan(axis));
  74. }
  75. return super.getPreferredSpan(axis);
  76. }
  77. public float getMaximumSpan(int axis) {
  78. if (axis == View.X_AXIS && isVisible()) {
  79. // Default to preferred.
  80. return Math.max(30, super.getMaximumSpan(axis));
  81. }
  82. return super.getMaximumSpan(axis);
  83. }
  84. // DocumentListener methods
  85. public void insertUpdate(DocumentEvent e) {
  86. pushTextToModel();
  87. }
  88. public void removeUpdate(DocumentEvent e) {
  89. pushTextToModel();
  90. }
  91. public void changedUpdate(DocumentEvent e) {
  92. pushTextToModel();
  93. }
  94. // View method
  95. public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
  96. if (!isSettingAttributes) {
  97. isSettingAttributes = true;
  98. try {
  99. getTextComponent().setText(getRepresentedText());
  100. resetBorder();
  101. }
  102. finally {
  103. isSettingAttributes = false;
  104. }
  105. preferenceChanged(this, true, true);
  106. getContainer().repaint();
  107. }
  108. }
  109. // local methods
  110. void updateYAlign(Font font) {
  111. FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
  112. float h = fm.getHeight();
  113. float d = fm.getDescent();
  114. float yAlign = (h - d) / h;
  115. }
  116. void resetBorder() {
  117. if (isEndTag()) {
  118. ((JPanel)getComponent()).setBorder(EndBorder);
  119. }
  120. else {
  121. ((JPanel)getComponent()).setBorder(StartBorder);
  122. }
  123. }
  124. void pushTextToModel() {
  125. if (!isSettingAttributes) {
  126. Object name = getElement().getAttributes().getAttribute
  127. (StyleConstants.NameAttribute);
  128. Document doc = getDocument();
  129. if ((name instanceof HTML.UnknownTag) &&
  130. (doc instanceof StyledDocument)) {
  131. SimpleAttributeSet sas = new SimpleAttributeSet();
  132. String text = getTextComponent().getText();
  133. isSettingAttributes = true;
  134. try {
  135. sas.addAttribute(StyleConstants.NameAttribute,
  136. new HTML.UnknownTag(text));
  137. ((StyledDocument)doc).setCharacterAttributes
  138. (getStartOffset(), getEndOffset() -
  139. getStartOffset(), sas, false);
  140. }
  141. finally {
  142. isSettingAttributes = false;
  143. }
  144. }
  145. }
  146. }
  147. JTextComponent getTextComponent() {
  148. return (JTextComponent)((Container)getComponent()).getComponent(0);
  149. }
  150. String getRepresentedText() {
  151. String retValue = getElement().getName();
  152. return (retValue == null) ? "" : retValue;
  153. }
  154. boolean isEndTag() {
  155. AttributeSet as = getElement().getAttributes();
  156. if (as != null) {
  157. Object end = as.getAttribute(HTML.Attribute.ENDTAG);
  158. if (end != null && (end instanceof String) &&
  159. ((String)end).equals("true")) {
  160. return true;
  161. }
  162. }
  163. return false;
  164. }
  165. /** Alignment along the y axis, based on the font of the textfield. */
  166. float yAlign;
  167. /** Set to true when setting attributes. */
  168. boolean isSettingAttributes;
  169. // Following are for Borders that used for Unknown tags and comments.
  170. //
  171. // Border defines
  172. static final int circleR = 3;
  173. static final int circleD = circleR * 2;
  174. static final int tagSize = 6;
  175. static final int padding = 3;
  176. static final Color UnknownTagBorderColor = Color.black;
  177. static final Border StartBorder = new StartTagBorder();
  178. static final Border EndBorder = new EndTagBorder();
  179. static class StartTagBorder implements Border, Serializable {
  180. public void paintBorder(Component c, Graphics g, int x, int y,
  181. int width, int height) {
  182. g.setColor(UnknownTagBorderColor);
  183. x += padding;
  184. width -= (padding * 2);
  185. g.drawLine(x, y + circleR,
  186. x, y + height - circleR);
  187. g.drawArc(x, y + height - circleD - 1,
  188. circleD, circleD, 180, 90);
  189. g.drawArc(x, y, circleD, circleD, 90, 90);
  190. g.drawLine(x + circleR, y, x + width - tagSize, y);
  191. g.drawLine(x + circleR, y + height - 1,
  192. x + width - tagSize, y + height - 1);
  193. g.drawLine(x + width - tagSize, y,
  194. x + width - 1, y + height / 2);
  195. g.drawLine(x + width - tagSize, y + height,
  196. x + width - 1, y + height / 2);
  197. }
  198. public Insets getBorderInsets(Component c) {
  199. return new Insets(2, 2 + padding, 2, tagSize + 2 + padding);
  200. }
  201. public boolean isBorderOpaque() {
  202. return false;
  203. }
  204. } // End of class HiddenTagView.StartTagBorder
  205. static class EndTagBorder implements Border, Serializable {
  206. public void paintBorder(Component c, Graphics g, int x, int y,
  207. int width, int height) {
  208. g.setColor(UnknownTagBorderColor);
  209. x += padding;
  210. width -= (padding * 2);
  211. g.drawLine(x + width - 1, y + circleR,
  212. x + width - 1, y + height - circleR);
  213. g.drawArc(x + width - circleD - 1, y + height - circleD - 1,
  214. circleD, circleD, 270, 90);
  215. g.drawArc(x + width - circleD - 1, y, circleD, circleD, 0, 90);
  216. g.drawLine(x + tagSize, y, x + width - circleR, y);
  217. g.drawLine(x + tagSize, y + height - 1,
  218. x + width - circleR, y + height - 1);
  219. g.drawLine(x + tagSize, y,
  220. x, y + height / 2);
  221. g.drawLine(x + tagSize, y + height,
  222. x, y + height / 2);
  223. }
  224. public Insets getBorderInsets(Component c) {
  225. return new Insets(2, tagSize + 2 + padding, 2, 2 + padding);
  226. }
  227. public boolean isBorderOpaque() {
  228. return false;
  229. }
  230. } // End of class HiddenTagView.EndTagBorder
  231. } // End of HiddenTagView