/plugins/XML/tags/release-2-0-6/xml/EditTagDialog.java

# · Java · 603 lines · 449 code · 86 blank · 68 comment · 70 complexity · dec01608aa22405c484808851bb1be7e MD5 · raw file

  1. /*
  2. * EditTagDialog.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2000, 2003 Slava Pestov
  7. *
  8. * The XML plugin is licensed under the GNU General Public License, with
  9. * the following exception:
  10. *
  11. * "Permission is granted to link this code with software released under
  12. * the Apache license version 1.1, for example used by the Xerces XML
  13. * parser package."
  14. */
  15. package xml;
  16. //{{{ Imports
  17. import javax.swing.table.*;
  18. import javax.swing.border.*;
  19. import javax.swing.*;
  20. import java.awt.event.*;
  21. import java.awt.BorderLayout;
  22. import java.awt.Component;
  23. import java.awt.Dimension;
  24. import java.util.*;
  25. import org.gjt.sp.jedit.gui.*;
  26. import org.gjt.sp.jedit.*;
  27. import xml.completion.*;
  28. //}}}
  29. class EditTagDialog extends EnhancedDialog
  30. {
  31. //{{{ EditTagDialog constructor
  32. /**
  33. * elementName might not equal element.name due to case insensitivity
  34. * in HTML files.
  35. */
  36. EditTagDialog(View view, String elementName, ElementDecl element,
  37. Map attributeValues, boolean elementEmpty, Map entityHash,
  38. List ids, boolean html)
  39. {
  40. super(view,jEdit.getProperty("xml-edit-tag.title"),true);
  41. this.elementName = elementName;
  42. this.element = element;
  43. this.entityHash = entityHash;
  44. this.html = html;
  45. JPanel content = new JPanel(new BorderLayout());
  46. content.setBorder(new EmptyBorder(12,12,12,12));
  47. setContentPane(content);
  48. //{{{ Top panel with element name, empty toggle
  49. JPanel top = new JPanel(new BorderLayout(6,0));
  50. top.setBorder(new EmptyBorder(0,0,12,0));
  51. top.add(BorderLayout.WEST,new JLabel(
  52. jEdit.getProperty("xml-edit-tag.element-name")));
  53. top.add(BorderLayout.CENTER,new JLabel(element.name));
  54. empty = new JCheckBox(jEdit.getProperty("xml-edit-tag.empty"));
  55. if(element.empty)
  56. {
  57. empty.setSelected(true);
  58. empty.setEnabled(false);
  59. }
  60. else
  61. empty.setSelected(elementEmpty);
  62. empty.addActionListener(new ActionHandler());
  63. top.add(BorderLayout.EAST,empty);
  64. content.add(BorderLayout.NORTH,top);
  65. //}}}
  66. //{{{ Attribute table
  67. JPanel center = new JPanel(new BorderLayout());
  68. attributeModel = createAttributeModel(element.attributes,
  69. attributeValues,ids);
  70. attributes = new AttributeTable();
  71. attributes.setModel(new AttributeTableModel());
  72. attributes.setRowHeight(new JComboBox(new String[] { "template" })
  73. .getPreferredSize().height);
  74. attributes.getTableHeader().setReorderingAllowed(false);
  75. attributes.getColumnModel().getColumn(0).setPreferredWidth(30);
  76. attributes.setColumnSelectionAllowed(false);
  77. attributes.setRowSelectionAllowed(false);
  78. attributes.setCellSelectionEnabled(false);
  79. JScrollPane scroller = new JScrollPane(attributes);
  80. Dimension size = scroller.getPreferredSize();
  81. size.height = Math.min(size.width,200);
  82. scroller.setPreferredSize(size);
  83. center.add(BorderLayout.CENTER,scroller);
  84. //}}}
  85. //{{{ Preview field
  86. JPanel previewPanel = new JPanel(new BorderLayout());
  87. previewPanel.setBorder(new EmptyBorder(12,0,0,0));
  88. previewPanel.add(BorderLayout.NORTH,new JLabel(jEdit.getProperty(
  89. "xml-edit-tag.preview")));
  90. preview = new JTextArea(5,5);
  91. preview.setLineWrap(true);
  92. preview.setWrapStyleWord(true);
  93. preview.setEditable(false);
  94. previewPanel.add(BorderLayout.CENTER,new JScrollPane(preview));
  95. center.add(BorderLayout.SOUTH,previewPanel);
  96. //}}}
  97. content.add(BorderLayout.CENTER,center);
  98. //{{{ Buttons
  99. JPanel buttons = new JPanel();
  100. buttons.setLayout(new BoxLayout(buttons,BoxLayout.X_AXIS));
  101. buttons.setBorder(new EmptyBorder(12,0,0,0));
  102. buttons.add(Box.createGlue());
  103. buttons.add(ok = new JButton(jEdit.getProperty("common.ok")));
  104. ok.addActionListener(new ActionHandler());
  105. getRootPane().setDefaultButton(ok);
  106. buttons.add(Box.createHorizontalStrut(6));
  107. buttons.add(cancel = new JButton(jEdit.getProperty("common.cancel")));
  108. cancel.addActionListener(new ActionHandler());
  109. buttons.add(cancel);
  110. buttons.add(Box.createGlue());
  111. content.add(BorderLayout.SOUTH,buttons);
  112. //}}}
  113. updateTag();
  114. setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  115. pack();
  116. setLocationRelativeTo(view);
  117. setVisible(true);
  118. } //}}}
  119. //{{{ ok() method
  120. public void ok()
  121. {
  122. int row = attributes.getSelectedRow();
  123. int column = attributes.getSelectedColumn();
  124. if(row != -1 && column != -1)
  125. {
  126. if(attributes.getCellEditor(row,column) != null)
  127. attributes.getCellEditor(row,column).stopCellEditing();
  128. }
  129. isOK = true;
  130. dispose();
  131. } //}}}
  132. //{{{ cancel() method
  133. public void cancel()
  134. {
  135. isOK = false;
  136. dispose();
  137. } //}}}
  138. //{{{ getNewTag() method
  139. public String getNewTag()
  140. {
  141. return (isOK ? newTag : null);
  142. } //}}}
  143. //{{{ isEmpty() method
  144. public boolean isEmpty()
  145. {
  146. return empty.isSelected();
  147. } //}}}
  148. //{{{ Private members
  149. //{{{ Instance variables
  150. private boolean html;
  151. private String elementName;
  152. private ElementDecl element;
  153. private Map entityHash;
  154. private JCheckBox empty;
  155. private List attributeModel;
  156. private JTable attributes;
  157. private JTextArea preview;
  158. private JButton ok;
  159. private JButton cancel;
  160. private String newTag;
  161. private boolean isOK;
  162. //}}}
  163. //{{{ createAttributeModel() method
  164. private ArrayList createAttributeModel(List declaredAttributes,
  165. Map attributeValues, List ids)
  166. {
  167. ArrayList stringIDs = new ArrayList(ids.size());
  168. for(int i = 0; i < ids.size(); i++)
  169. {
  170. stringIDs.add(((IDDecl)ids.get(i)).id);
  171. }
  172. ArrayList attributeModel = new ArrayList();
  173. for(int i = 0; i < declaredAttributes.size(); i++)
  174. {
  175. ElementDecl.AttributeDecl attr =
  176. (ElementDecl.AttributeDecl)
  177. declaredAttributes.get(i);
  178. boolean set;
  179. String value = (String)attributeValues.get(attr.name);
  180. if(value == null)
  181. {
  182. set = false;
  183. value = attr.value;
  184. }
  185. else
  186. set = true;
  187. if(attr.required)
  188. set = true;
  189. ArrayList values;
  190. if(attr.type.equals("IDREF")
  191. && stringIDs.size() > 0)
  192. {
  193. values = stringIDs;
  194. if(value == null)
  195. value = (String)stringIDs.get(0);
  196. }
  197. else
  198. {
  199. values = attr.values;
  200. if(value == null && values != null
  201. && values.size() > 0)
  202. value = (String)values.get(0);
  203. }
  204. attributeModel.add(new Attribute(set,attr.name,
  205. value,values,attr.type,attr.required));
  206. }
  207. Collections.sort(attributeModel,new AttributeCompare());
  208. return attributeModel;
  209. } //}}}
  210. //{{{ updateTag() method
  211. private void updateTag()
  212. {
  213. int tagNameCase = TextUtilities.getStringCase(elementName);
  214. StringBuffer buf = new StringBuffer("<");
  215. buf.append(elementName);
  216. for(int i = 0; i < attributeModel.size(); i++)
  217. {
  218. Attribute attr = (Attribute)attributeModel.get(i);
  219. if(!attr.set)
  220. continue;
  221. buf.append(' ');
  222. String attrName = attr.name;
  223. if(html)
  224. {
  225. switch(tagNameCase)
  226. {
  227. case TextUtilities.UPPER_CASE:
  228. attrName = attr.name.toUpperCase();
  229. break;
  230. case TextUtilities.LOWER_CASE:
  231. attrName = attr.name.toLowerCase();
  232. break;
  233. case TextUtilities.TITLE_CASE:
  234. attrName = TextUtilities.toTitleCase(
  235. attr.name);
  236. break;
  237. }
  238. }
  239. buf.append(attr.name);
  240. if(html && attr.name.equals(attr.value.value))
  241. {
  242. continue;
  243. }
  244. buf.append("=\"");
  245. if(attr.value.value != null)
  246. {
  247. buf.append(XmlActions.charactersToEntities(
  248. attr.value.value,entityHash));
  249. }
  250. buf.append("\"");
  251. }
  252. if(empty.isSelected() && !html)
  253. buf.append("/");
  254. buf.append(">");
  255. newTag = buf.toString();
  256. preview.setText(newTag);
  257. } //}}}
  258. //}}}
  259. //{{{ Inner classes
  260. //{{{ ActionHandler class
  261. class ActionHandler implements ActionListener
  262. {
  263. public void actionPerformed(ActionEvent evt)
  264. {
  265. if(evt.getSource() == empty)
  266. updateTag();
  267. else if(evt.getSource() == ok)
  268. ok();
  269. else if(evt.getSource() == cancel)
  270. cancel();
  271. }
  272. } //}}}
  273. //{{{ Attribute class
  274. static class Attribute
  275. {
  276. //{{{ Instance variables
  277. boolean set;
  278. String name;
  279. Value value;
  280. String type;
  281. boolean required;
  282. //}}}
  283. //{{{ Attribute constructor
  284. Attribute(boolean set, String name,
  285. String value, ArrayList values,
  286. String type, boolean required)
  287. {
  288. this.set = set;
  289. this.name = name;
  290. this.value = new Value(value,values);
  291. this.type = type;
  292. this.required = required;
  293. } //}}}
  294. //{{{ Value class
  295. static class Value
  296. {
  297. String value;
  298. ArrayList values;
  299. Value(String value, ArrayList values)
  300. {
  301. this.value = value;
  302. this.values = values;
  303. }
  304. public String toString()
  305. {
  306. return value;
  307. }
  308. } //}}}
  309. } //}}}
  310. //{{{ AttributeCompare class
  311. static class AttributeCompare implements MiscUtilities.Compare
  312. {
  313. public int compare(Object obj1, Object obj2)
  314. {
  315. Attribute attr1 = (Attribute)obj1;
  316. Attribute attr2 = (Attribute)obj2;
  317. // put required attributes at the top
  318. if(attr1.required && !attr2.required)
  319. return -1;
  320. else if(!attr1.required && attr2.required)
  321. return 1;
  322. else
  323. {
  324. return MiscUtilities.compareStrings(
  325. attr1.name,attr2.name,true);
  326. }
  327. }
  328. } //}}}
  329. static ComboValueRenderer comboRenderer = new ComboValueRenderer();
  330. //{{{ AttributeTable class
  331. class AttributeTable extends JTable
  332. {
  333. //{{{ getCellEditor() method
  334. public TableCellEditor getCellEditor(int row, int column)
  335. {
  336. Object value = getModel().getValueAt(row,column);
  337. if(value instanceof Attribute.Value)
  338. return comboRenderer;
  339. return super.getCellEditor(row,column);
  340. } //}}}
  341. //{{{ getCellRenderer() method
  342. public TableCellRenderer getCellRenderer(int row, int column)
  343. {
  344. Object value = getModel().getValueAt(row,column);
  345. if(value instanceof Attribute.Value)
  346. return comboRenderer;
  347. return super.getCellRenderer(row,column);
  348. } //}}}
  349. } //}}}
  350. //{{{ AttributeTableModel class
  351. class AttributeTableModel extends AbstractTableModel
  352. {
  353. //{{{ getColumnCount() method
  354. public int getColumnCount()
  355. {
  356. return 4;
  357. } //}}}
  358. //{{{ getRowCount() method
  359. public int getRowCount()
  360. {
  361. return attributeModel.size();
  362. } //}}}
  363. //{{{ getColumnClass() method
  364. public Class getColumnClass(int col)
  365. {
  366. if(col == 0)
  367. return Boolean.class;
  368. else
  369. return String.class;
  370. } //}}}
  371. //{{{ getColumnName() method
  372. public String getColumnName(int col)
  373. {
  374. switch(col)
  375. {
  376. case 0:
  377. return jEdit.getProperty("xml-edit-tag.set");
  378. case 1:
  379. return jEdit.getProperty("xml-edit-tag.attribute");
  380. case 2:
  381. return jEdit.getProperty("xml-edit-tag.type");
  382. case 3:
  383. return jEdit.getProperty("xml-edit-tag.value");
  384. default:
  385. throw new InternalError();
  386. }
  387. } //}}}
  388. //{{{ isCellEditable() method
  389. public boolean isCellEditable(int row, int col)
  390. {
  391. if(col != 1 && col != 2)
  392. return true;
  393. else
  394. return false;
  395. } //}}}
  396. //{{{ getValueAt() method
  397. public Object getValueAt(int row, int col)
  398. {
  399. Attribute attr = (Attribute)attributeModel.get(row);
  400. switch(col)
  401. {
  402. case 0:
  403. return new Boolean(attr.set);
  404. case 1:
  405. return attr.name;
  406. case 2:
  407. if(attr.required)
  408. {
  409. if(attr.type.startsWith("("))
  410. return jEdit.getProperty("xml-edit-tag.required");
  411. else
  412. return attr.type + ", " + jEdit.getProperty("xml-edit-tag.required");
  413. }
  414. else if(attr.type.startsWith("("))
  415. return "";
  416. else
  417. return attr.type;
  418. case 3:
  419. if(attr.value.values != null)
  420. return attr.value;
  421. else
  422. return attr.value.value;
  423. default:
  424. throw new InternalError();
  425. }
  426. } //}}}
  427. //{{{ setValueAt() method
  428. public void setValueAt(Object value, int row, int col)
  429. {
  430. Attribute attr = (Attribute)attributeModel.get(row);
  431. switch(col)
  432. {
  433. case 0:
  434. if(attr.required)
  435. return;
  436. attr.set = ((Boolean)value).booleanValue();
  437. break;
  438. case 3:
  439. String sValue;
  440. if(value instanceof IDDecl)
  441. sValue = ((IDDecl)value).id;
  442. else
  443. sValue = value.toString();
  444. if(equal(attr.value.value,sValue))
  445. return;
  446. attr.set = true;
  447. attr.value.value = sValue;
  448. break;
  449. }
  450. fireTableRowsUpdated(row,row);
  451. updateTag();
  452. } //}}}
  453. //{{{ equal() method
  454. private boolean equal(String str1, String str2)
  455. {
  456. if(str1 == null || str1.length() == 0)
  457. {
  458. if(str2 == null || str2.length() == 0)
  459. return true;
  460. else
  461. return false;
  462. }
  463. else
  464. {
  465. if(str2 == null)
  466. return false;
  467. else
  468. return str1.equals(str2);
  469. }
  470. } //}}}
  471. } //}}}
  472. //{{{ ComboValueRenderer class
  473. static class ComboValueRenderer extends DefaultCellEditor
  474. implements TableCellRenderer
  475. {
  476. JComboBox editorCombo;
  477. JComboBox renderCombo;
  478. //{{{ ComboValueRenderer constructor
  479. ComboValueRenderer()
  480. {
  481. this(new JComboBox());
  482. } //}}}
  483. //{{{ ComboValueRenderer constructor
  484. // this is stupid. why can't you reference instance vars
  485. // in a super() invocation?
  486. ComboValueRenderer(JComboBox comboBox)
  487. {
  488. super(comboBox);
  489. this.editorCombo = comboBox;
  490. editorCombo.setEditable(true);
  491. this.renderCombo = new JComboBox();
  492. renderCombo.setEditable(true);
  493. } //}}}
  494. //{{{ getTableCellEditorComponent() method
  495. public Component getTableCellEditorComponent(JTable table,
  496. Object value, boolean isSelected, int row, int column)
  497. {
  498. Attribute.Value _value = (Attribute.Value)value;
  499. editorCombo.setModel(new DefaultComboBoxModel(
  500. _value.values.toArray()));
  501. return super.getTableCellEditorComponent(table,
  502. _value.value,isSelected,row,column);
  503. } //}}}
  504. //{{{ getTableCellRendererComponent() method
  505. public Component getTableCellRendererComponent(JTable table,
  506. Object value, boolean isSelected, boolean hasFocus,
  507. int row, int column)
  508. {
  509. Attribute.Value _value = (Attribute.Value)value;
  510. renderCombo.setModel(new DefaultComboBoxModel(
  511. _value.values.toArray()));
  512. renderCombo.setSelectedItem(_value.value);
  513. return renderCombo;
  514. } //}}}
  515. } //}}}
  516. //}}}
  517. }