001:/*
002: * Copyright (c) 2000, Jacob Smullyan.
003: *
004: * This is part of SkunkDAV, a WebDAV client. See http://skunkdav.sourceforge.net/
005: * for the latest version.
006: *
007: * SkunkDAV is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License as published
009: * by the Free Software Foundation; either version 2, or (at your option)
010: * any later version.
011: *
012: * SkunkDAV is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with SkunkDAV; see the file COPYING. If not, write to the Free
019: * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
020: * 02111-1307, USA.
021:*/
022:
023:
024:package org.skunk.spi;
025:
026:import java.awt.BorderLayout;
027:import java.awt.Component;
028:import java.awt.Dimension;
029:import java.awt.Font;
030:import java.awt.GridBagConstraints;
031:import java.awt.GridBagLayout;
032:import java.awt.Insets;
033:import java.awt.Point;
034:import java.awt.event.ActionEvent;
035:import java.awt.event.MouseAdapter;
036:import java.awt.event.MouseEvent;
037:import java.awt.event.MouseMotionListener;
038:import java.io.UnsupportedEncodingException;
039:import java.util.ArrayList;
040:import java.util.HashMap;
041:import java.util.Iterator;
042:import java.util.Map;
043:import java.util.TreeMap;
044:import javax.swing.AbstractAction;
045:import javax.swing.BorderFactory;
046:import javax.swing.Box;
047:import javax.swing.BoxLayout;
048:import javax.swing.JButton;
049:import javax.swing.JComponent;
050:import javax.swing.JLabel;
051:import javax.swing.JOptionPane;
052:import javax.swing.JPanel;
053:import javax.swing.JScrollPane;
054:import javax.swing.JSplitPane;
055:import javax.swing.JTabbedPane;
056:import javax.swing.JTable;
057:import javax.swing.JTextArea;
058:import javax.swing.ListSelectionModel;
059:import javax.swing.SwingConstants;
060:import javax.swing.border.Border;
061:import javax.swing.event.DocumentEvent;
062:import javax.swing.event.DocumentListener;
063:import javax.swing.event.ListSelectionEvent;
064:import javax.swing.event.ListSelectionListener;
065:import javax.swing.table.AbstractTableModel;
066:import javax.swing.table.TableModel;
067:import javax.swing.text.BadLocationException;
068:import javax.swing.text.Document;
069:import org.skunk.assert.Assertion;
070:import org.skunk.dav.client.DAVFile;
071:import org.skunk.dav.client.gui.ExplorerApp;
072:import org.skunk.dav.client.gui.ResourceManager;
073:import org.skunk.dav.client.gui.editor.AbstractDAVEditor;
074:import org.skunk.dav.client.gui.editor.CannotLoadException;
075:import org.skunk.dav.client.gui.editor.DAVEditorUndoManager;
076:import org.skunk.trace.Debug;
077:
078:/**
079: * facility for editing Skunk message catalogs.
080: * need to support cut, copy and paste;
081: * undo, if the layout does not make that confusing.
082: */
083:public class MessageCatalogEditor extends AbstractDAVEditor
084:{
085: private JComponent edComp;
086: private JComponent messageDisplay;
087: private JSplitPane splitter;
088: private Map messageMap=null;
089: private MessageCatalogTableModel tableModel;
090: private Map.Entry selectedMessage;
091: private volatile int selectedTableRow=-99;
092: private boolean complex;
093: private JLabel currentLabel;
094: private JTable currentTable;
095: private HashMap messageDisplayMap=new HashMap();
096: private static final int UNSELECTED=-99;
097: public static final String ISO_LATIN_1="8859_1";
098:
099: public MessageCatalogEditor(DAVFile file)
100: {
101: super (file);
102: }
103:
104: public DAVEditorUndoManager getUndoManager()
105: {
106: return null;
107: }
108:
109: private void initModel()
110: {
111: tableModel =new MessageCatalogTableModel();
112: }
113:
114: private void initComponents()
115: {
116: edComp=new JPanel(new BorderLayout());
117: splitter=new JSplitPane(JSplitPane.VERTICAL_SPLIT);
118: splitter.setTopComponent(createMessageTable());
119: splitter.setBottomComponent(createMessageDisplay());
120: splitter.setDividerLocation(0.5);
121: edComp.add(splitter, BorderLayout.CENTER);
122: edComp.add(createButtonPanel(), BorderLayout.SOUTH);
123: }
124:
125: private JComponent createMessageTable()
126: {
127: TableSelectionListener tsl=new TableSelectionListener();
128: JTable table=new JTable(tableModel);
129: table.getTableHeader().setReorderingAllowed(false);
130: table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
131: currentTable=table;
132: table.addMouseListener(tsl);
133: table.addMouseMotionListener(tsl);
134: table.getSelectionModel().addListSelectionListener(tsl);
135: if (table.getRowCount()>0)
136: table.setRowSelectionInterval(0, 0);
137: JScrollPane scroller=new JScrollPane(table);
138: try
139: {
140: Dimension d=ExplorerApp.getAppContext().getCurrentView().getFocussedBuffer().getComponent().getSize();
141: Dimension newDim=new Dimension(d.width, d.height/2);
142: scroller.setPreferredSize(newDim);
143: }
144: catch (NullPointerException e) {}
145: return scroller;
146: }
147:
148: private void selectFirstRow()
149: {
150: selectedTableRow=UNSELECTED;
151: if (currentTable.getRowCount()>0)
152: currentTable.setRowSelectionInterval(0, 0);
153: }
154:
155: private void selectRow(Object key)
156: {
157: selectedTableRow=UNSELECTED;
158: if (key==null) return;
159: int i=0;
160: for (Iterator it=messageMap.keySet().iterator();it.hasNext();i++)
161: {
162: if (key.equals(it.next()) && currentTable.getRowCount()>i)
163: {
164: currentTable.setRowSelectionInterval(i, i);
165: break;
166: }
167: }
168: }
169:
170: private void displayMessage()
171: {
172: Component c=splitter.getBottomComponent();
173: if (c!=null)
174: splitter.remove(c);
175: messageDisplay=null;
176: messageDisplay=getMessageDisplay(selectedMessage);
177: splitter.setBottomComponent(messageDisplay);
178: messageDisplay.revalidate();
179: }
180:
181: private void showTab(int tab)
182: {
183: if (isComplex()
184: && messageDisplay instanceof MessageDisplay)
185: ((MessageDisplay) messageDisplay).showTab(tab);
186: }
187:
188: private JComponent createMessageDisplay()
189: {
190: if (selectedMessage==null)
191: {
192: messageDisplay=new JPanel();
193: }
194: else
195: {
196: messageDisplay=getMessageDisplay(selectedMessage);
197: }
198:
199: JScrollPane scroller=new JScrollPane(messageDisplay);
200: scroller.setPreferredSize(messageDisplay.getPreferredSize());
201: return scroller;
202: }
203:
204: private JComponent getMessageDisplay(Map.Entry message)
205: {
206: if (message==null)
207: return new JPanel();
208: Object key=message.getKey();
209: if (messageDisplayMap.containsKey(key))
210: {
211: MessageDisplay display = (MessageDisplay) messageDisplayMap.get(key);
212: return display;
213: }
214: else
215: {
216: MessageDisplay display=new MessageDisplay(message);
217: messageDisplayMap.put(message.getKey(), display);
218: return display;
219: }
220: }
221:
222:
223: private class MessageDisplay extends JPanel
224: {
225: private Map.Entry message;
226: private Dimension dim=new Dimension(400, 150);
227: private JTabbedPane tabPane;
228: private ArrayList complexTextAreas=new ArrayList();
229: private JTextArea simpleTextArea;
230:
231: MessageDisplay(Map.Entry message)
232: {
233: super ();
234: this .message=message;
235: initMessageDisplayComponents();
236: }
237:
238: Map.Entry getMessage()
239: {
240: return this .message;
241: }
242:
243: void showTab(int tab)
244: {
245: if (tabPane!=null
246: && tab >=0
247: && tab<tabPane.getTabCount())
248: {
249: tabPane.setSelectedIndex(tab);
250: JTextArea jta=(JTextArea)complexTextAreas.get(tab);
251: jta.requestFocus();
252: jta.getCaret().setVisible(true);
253: }
254: }
255:
256: void focus()
257: {
258: JTextArea jta;
259: if (isComplex())
260: {
261: jta=(JTextArea)complexTextAreas.get(tabPane.getSelectedIndex());
262: }
263: else
264: {
265: jta=simpleTextArea;
266: }
267: jta.requestFocus();
268: jta.getCaret().setVisible(true);
269: }
270:
271: void initMessageDisplayComponents()
272: {
273: if (this .message==null)
274: {
275: return;
276: }
277: int columnCount=MessageCatalogEditor.this .tableModel.getColumnCount();
278:
279: setLayout(new GridBagLayout());
280: GridBagConstraints gbc=new GridBagConstraints();
281: gbc.gridx=0;
282: gbc.gridy=0;
283: gbc.gridwidth=1;
284: gbc.gridheight=1;
285: gbc.fill=GridBagConstraints.HORIZONTAL;
286: gbc.anchor=GridBagConstraints.NORTHWEST;
287: gbc.insets=new Insets(2, 2, 2, 2);
288: JLabel keyLabel=new JLabel();
289: keyLabel.setFont(new Font("Dialog", Font.BOLD, 16));
290: keyLabel.setText(message.getKey().toString());
291: add(keyLabel, gbc);
292: MessageCatalogEditor.this .currentLabel=keyLabel;
293: gbc.gridy++;
294: if (!MessageCatalogEditor.this .isComplex())
295: {
296: simpleTextArea=new JTextArea(message.getValue().toString(), 10, 60);
297: simpleTextArea.getDocument().addDocumentListener(new MessageDocumentListener(message));
298: add(new JScrollPane(simpleTextArea), gbc);
299: }
300: else
301: {
302: tabPane=new JTabbedPane();
303: tabPane.setTabPlacement(SwingConstants.RIGHT);
304: Object value=message.getValue();
305: Assertion.assert((value instanceof Map), "selected Message value is a Map");
306: Map currentValues=(Map) value;
307: for (Iterator it=currentValues.keySet().iterator();it.hasNext();)
308: {
309: Object langKey=it.next();
310: String messageStr=currentValues.get(langKey).toString();
311: JTextArea textarea=new JTextArea(messageStr, 10, 60);
312: complexTextAreas.add(textarea);
313: textarea.getDocument().addDocumentListener(new MessageDocumentListener(message,
314: langKey));
315: tabPane.addTab(langKey.toString(), new JScrollPane(textarea));
316: }
317: add(tabPane, gbc);
318: }
319: }
320:
321: public Dimension getPreferredSize()
322: {
323: return dim;
324: }
325:
326: public Dimension getMinimumSize()
327: {
328: return dim;
329: }
330:
331: public Dimension getMaximumSize()
332: {
333: return dim;
334: }
335: }
336:
337: public static final TreeMap newSimpleCatalog()
338: {
339: return new TreeMap();
340: }
341:
342: public static final TreeMap newComplexCatalog()
343: {
344: TreeMap subTm=new TreeMap();
345: subTm.put("eng", "");
346: subTm.put("por", "");
347: subTm.put("esp", "");
348: TreeMap tm=new TreeMap();
349: tm.put("", subTm);
350: return tm;
351: }
352:
353: private JComponent createButtonPanel()
354: {
355: JPanel boxPanel=new JPanel();
356: boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.X_AXIS));
357: JButton addButton=new JButton(ResourceManager.getMessage(ResourceManager.ADD_MESSAGE));
358: addButton.addActionListener(new AddMessageAction());
359: JButton removeButton=new JButton(ResourceManager.getMessage(ResourceManager.REMOVE_MESSAGE));
360: removeButton.addActionListener(new RemoveMessageAction());
361: JButton renameButton=new JButton(ResourceManager.getMessage(ResourceManager.RENAME_MESSAGE));
362: renameButton.addActionListener(new RenameMessageAction());
363: boxPanel.add(Box.createHorizontalGlue());
364: boxPanel.add(addButton);
365: boxPanel.add(Box.createHorizontalStrut(5));
366: boxPanel.add(removeButton);
367: boxPanel.add(Box.createHorizontalStrut(5));
368: boxPanel.add(renameButton);
369: boxPanel.add(Box.createHorizontalGlue());
370: Border outerBorder=BorderFactory.createLoweredBevelBorder();
371: Border innerBorder=BorderFactory.createEmptyBorder(10, 10, 10, 10);
372: boxPanel.setBorder(BorderFactory.createCompoundBorder(outerBorder, innerBorder));
373: return boxPanel;
374: }
375:
376: public void load() throws CannotLoadException
377: {
378: byte[] body=getResourceBody();
379: if (body==null || body.length==0)
380: {
381: if (getResourceName().endsWith(".cat"))
382: {
383: messageMap=newComplexCatalog();
384: complex=true;
385: }
386: else
387: {
388: messageMap=newSimpleCatalog();
389: complex=false;
390: }
391: }
392: else try
393: {
394: messageMap = invert(DictParser.fromString(new String(getResourceBody())));
395:
396: // or use org.skunk.spi MessageHasher, which is a jythonc'ed class:
397: // MessageHasher hasher=new MessageHasher();
398: // messageMap=invert(hasher.stringToHash(new String(getResourceBody())));
399:
400: }
401: catch (Assertion badAss)
402: {
403: JOptionPane.showMessageDialog(ExplorerApp.getAppContext().getCurrentView().getFocussedBuffer().getComponent(),
404: ResourceManager.getMessage(ResourceManager.CANNOT_OPEN),
405: ResourceManager.getMessage(ResourceManager.ERROR_DIALOG_TITLE),
406: JOptionPane.ERROR_MESSAGE);
407: throw new CannotLoadException("cannot load file "+getResourceName());
408: }
409: initModel();
410: initComponents();
411: }
412:
413: public void save()
414: {
415: String s=DictParser.toString(invert(messageMap));
416:
417: //or, using MessageHasher:
418: //MessageHasher hasher=new MessageHasher();
419: //String s=invert(hasher.hashToString(messageMap));
420: try
421: {
422: setResourceBody(s.getBytes(ISO_LATIN_1));
423: }
424: catch (UnsupportedEncodingException uee)
425: {
426: Debug.trace(this , Debug.DP2, uee);
427: setResourceBody(s.getBytes());
428: }
429: super .save();
430: }
431:
432: /**
433: * takes a two-dimensional tabular structure like:
434: *
435: * {
436: * a => { x => fa, y => ga, z => ha },
437: * b => { x => fb, y => gb, z => hb }
438: * }
439: *
440: * and inverts its dimensions, returning:
441: *
442: * {
443: * x => { a => fa, b => fb },
444: * y => { a => ga, b => gb },
445: * z => { a => ha, b => hb }
446: * }
447: *
448: * one-dimensional structures are unaffected by inversion.
449: */
450: private TreeMap invert(Map m)
451: {
452: TreeMap retMap=new TreeMap();
453: try
454: {
455: for (Iterator it=m.keySet().iterator();it.hasNext();)
456: {
457: Object key=it.next();
458: Object value=m.get(key);
459: if (!(value instanceof Map))
460: {
461: complex=false;
462: return (m instanceof TreeMap)
463: ? (TreeMap) m
464: : new TreeMap(m);
465: }
466: Map tmp=(Map)value;
467: for (Iterator subIt=tmp.keySet().iterator(); subIt.hasNext();)
468: {
469: Object subKey=subIt.next();
470: if (retMap.containsKey(subKey))
471: {
472: Object retVal=retMap.get(subKey);
473: Assertion.assert((retVal instanceof Map),
474: "second level value for key {0} and subKey {1} is a Map",
475: new Object[] {key, subKey} );
476: Map subMap=(Map)retVal;
477: subMap.put(key, tmp.get(subKey));
478: }
479: else
480: {
481: Map subMap=new TreeMap();
482: subMap.put(key, tmp.get(subKey));
483: retMap.put(subKey, subMap);
484: }
485: }
486: }
487: complex=true;
488: return retMap;
489: }
490: catch (Assertion badAss)
491: {
492: Debug.trace(this ,
493: Debug.DP3,
494: "map not a consistent 2D tabular structure, cannot invert");
495: Debug.trace(this , Debug.DP3, badAss);
496: throw badAss;
497: }
498: }
499:
500: public JComponent getComponent()
501: {
502: return edComp;
503: }
504:
505: private Map getMessageMap()
506: {
507: return this .messageMap;
508: }
509:
510: public boolean isComplex()
511: {
512: return this .complex;
513: }
514:
515: public Object getBlankComplexValue()
516: {
517: TreeMap tm=new TreeMap();
518: for (int i=1;i<tableModel.getColumnCount();i++)
519: {
520: tm.put(tableModel.getColumnName(i), "");
521: }
522: return tm;
523: }
524:
525: private class AddMessageAction extends AbstractAction
526: {
527: public void actionPerformed(ActionEvent ae)
528: {
529: String newKey=JOptionPane.showInputDialog(getComponent(),
530: ResourceManager.getMessage(ResourceManager.NEW_MESSAGE_PROMPT));
531: if (newKey!=null)
532: {
533: Object blankVal=(isComplex())
534: ? getBlankComplexValue()
535: : "";
536: getMessageMap().put(newKey.trim(), blankVal);
537: tableModel.fireTableStructureChanged();
538: MessageCatalogEditor.this .setDirty(true);
539: MessageCatalogEditor.this .selectRow(newKey);
540: }
541: }
542: }
543:
544: private class RemoveMessageAction extends AbstractAction
545: {
546: public void actionPerformed(ActionEvent ae)
547: {
548: getMessageMap().remove(selectedMessage.getKey());
549: tableModel.fireTableStructureChanged();
550: MessageCatalogEditor.this .setDirty(true);
551: MessageCatalogEditor.this .selectFirstRow();
552: }
553: }
554:
555: private class RenameMessageAction extends AbstractAction
556: {
557: public void actionPerformed(ActionEvent ae)
558: {
559: String newKey=JOptionPane.showInputDialog(getComponent(),
560: ResourceManager.getMessage(ResourceManager.RENAME_MESSAGE_PROMPT));
561: if (newKey!=null)
562: {
563: newKey=newKey.trim();
564: Map.Entry entry=MessageCatalogEditor.this .selectedMessage;
565: Object oldKey=entry.getKey();
566: Object value=entry.getValue();
567: getMessageMap().remove(oldKey);
568: getMessageMap().put(newKey, value);
569: MessageCatalogEditor.this .messageDisplayMap.remove(oldKey);
570: tableModel.fireTableStructureChanged();
571: displayMessage();
572: MessageCatalogEditor.this .setDirty(true);
573: MessageCatalogEditor.this .selectRow(newKey);
574: }
575: }
576: }
577: /**
578: * the table admits only row selection, but clicking on a column corresponding to a tab in the message
579: * display will cause the corresponding tab to be displayed.
580: */
581: private class TableSelectionListener extends MouseAdapter implements ListSelectionListener, MouseMotionListener
582: {
583: public void valueChanged(ListSelectionEvent lassie)
584: {
585: if ((!isComplex())
586: || MessageCatalogEditor.this .selectedTableRow==UNSELECTED)
587: {
588: Debug.trace(this , Debug.DP3, "in valueChanged()");
589: ListSelectionModel listModel=(ListSelectionModel)lassie.getSource();
590: int row=listModel.getMinSelectionIndex();
591: changeSelection(row, -1);
592: }
593: }
594:
595: private void changeSelection(int row, int column)
596: {
597: Debug.trace(this , Debug.DP3, "in changeSelection: row "+row +", column: "+column);
598: if (row!=MessageCatalogEditor.this .selectedTableRow)
599: {
600: MessageCatalogEditor.this .selectedTableRow=row;
601: Map.Entry entry=getEntry(row);
602: if (entry!=null)
603: {
604: MessageCatalogEditor.this .selectedMessage=entry;
605: MessageCatalogEditor.this .displayMessage();
606: }
607: }
608: if (isComplex()) //list selection events won't have any effect on columns
609: {
610: showTab((column>0)
611: ? column-1
612: : 0);
613: }
614: else if (MessageCatalogEditor.this .messageDisplay instanceof MessageDisplay)
615: {
616: ((MessageDisplay)MessageCatalogEditor.this .messageDisplay).focus();
617: }
618: }
619:
620: public void mouseMoved(MouseEvent moo)
621: {
622: //do nothing
623: }
624:
625: public void mouseClicked(MouseEvent moo)
626: {
627: if (isComplex())
628: {
629: Debug.trace(this , Debug.DP3, "in mouseClicked()");
630: JTable table=(JTable) moo.getSource();
631: Point p=new Point(moo.getX(), moo.getY());
632: int row=table.rowAtPoint(p);
633: int column=table.columnAtPoint(p);
634: changeSelection(row, column);
635: }
636: }
637:
638: public void mouseDragged(MouseEvent moo)
639: {
640: mouseClicked(moo);
641: }
642:
643: private Map.Entry getEntry(int row)
644: {
645: Iterator it=getMessageMap().entrySet().iterator();
646: for (int i=0;it.hasNext() && i<=row;i++)
647: {
648: Object o=it.next();
649: if (i==row && o instanceof Map.Entry)
650: return (Map.Entry) o;
651: }
652: return null;
653: }
654: }
655:
656: private class MessageCatalogTableModel extends AbstractTableModel
657: {
658: private int columnCount=-1;
659: public int getRowCount()
660: {
661: if (getMessageMap()!=null)
662: return getMessageMap().size();
663: else return 0;
664: }
665:
666: public String getColumnName(int column)
667: {
668: if (column==0)
669: return ResourceManager.getMessage(ResourceManager.KEY);
670: if (getColumnCount()==2 && column==1)
671: {
672: return ResourceManager.getMessage(ResourceManager.MESSAGE);
673: }
674:
675: Map mm=getMessageMap();
676: if (mm==null) return null;
677: Iterator it=mm.keySet().iterator();
678: Object randomVal=mm.get(it.next());
679: Assertion.assert((randomVal instanceof Map), "complex catalog has map for top-level value");
680: Map mm2=(Map)randomVal;
681: it=mm2.keySet().iterator();
682: for (int i=1;i<=column && it.hasNext();i++)
683: {
684: Object key=it.next();
685: if (i==column)
686: return key.toString();
687: }
688: return null;
689: }
690:
691: public int getColumnCount()
692: {
693: if (columnCount<=0)
694: {
695: Map mm=getMessageMap();
696: if (mm==null)
697: columnCount=0;
698: else
699: {
700: Iterator it=mm.keySet().iterator();
701: if (it.hasNext())
702: {
703: Object val=mm.get(it.next());
704: if (val instanceof Map)
705: {
706: Map subMap=(Map) val;
707: int size=subMap.size();
708: if (size>0)
709: {
710: columnCount= 1 + size; //one column for the key, one for each key in the sub-maps
711: }
712: }
713: }
714: if (columnCount<0)
715: columnCount=2; //key, value
716: }
717: }
718: return columnCount;
719: }
720:
721: public Object getValueAt(int row, int column)
722: {
723: Map mm=getMessageMap();
724: if (mm==null) return null;
725: Iterator it=mm.keySet().iterator();
726: for (int i=0;i<=row && it.hasNext();i++)
727: {
728: Object key=it.next();
729: if (i!=row)
730: continue;
731:
732: if (column==0)
733: {
734: return key;
735: }
736: Object value=mm.get(key);
737: if (value instanceof Map)
738: {
739: Map subMap=(Map)value;
740: Iterator subIt=subMap.keySet().iterator();
741: for (int j=1;j<=column && subIt.hasNext();j++)
742: {
743: Object subKey=subIt.next();
744: if (j==column)
745: {
746: return subMap.get(subKey);
747: }
748: }
749: }
750: else if (column==1)
751: return value;
752: }
753: return null;
754: }
755:
756: }
757:
758: private class MessageDocumentListener implements DocumentListener
759: {
760: private Map.Entry selectedMessage;
761: private Object langKey=null;
762:
763: MessageDocumentListener(Map.Entry selectedMessage)
764: {
765: this .selectedMessage=selectedMessage;
766: }
767:
768: MessageDocumentListener(Map.Entry selectedMessage, Object langKey)
769: {
770: this .selectedMessage=selectedMessage;
771: this .langKey=langKey;
772: }
773:
774: public void changedUpdate(DocumentEvent dee)
775: {
776: _update(dee);
777: }
778:
779: public void insertUpdate(DocumentEvent dee)
780: {
781: _update(dee);
782: }
783:
784: public void removeUpdate(DocumentEvent dee)
785: {
786: _update(dee);
787: }
788:
789: private void _update(DocumentEvent dee)
790: {
791: Document doc=dee.getDocument();
792: try
793: {
794: String text=doc.getText(0, doc.getLength());
795: if (langKey==null)
796: {
797: selectedMessage.setValue(text);
798: }
799: else
800: {
801: Object value=selectedMessage.getValue();
802: Assertion.assert((value instanceof Map), "selected message value is a Map");
803: Map m=(Map)value;
804: Assertion.assert(m.containsKey(langKey), "Map contains key"+langKey);
805: m.put(langKey, text);
806: }
807: MessageCatalogEditor.this .setDirty(true);
808: tableModel.fireTableRowsUpdated(MessageCatalogEditor.this .selectedTableRow,
809: MessageCatalogEditor.this .selectedTableRow);
810: }
811: catch (BadLocationException ballocks)
812: {
813: Debug.trace(this , Debug.DP2, ballocks);
814: }
815: }
816: }
817:}
818:
819:/* $Log: MessageCatalogEditor.java,v $
820:/* Revision 1.7 2001/07/11 02:06:15 smulloni
821:/* removed defunct spi files
822:/*
823:/* Revision 1.6 2000/12/19 22:36:06 smulloni
824:/* adjustments to preamble.
825:/*
826:/* Revision 1.5 2000/12/13 22:25:33 smulloni
827:/* now save catalogs explicitly in 8859_1 (ISO Latin-1) encoding
828:/*
829:/* Revision 1.4 2000/12/12 19:39:23 smulloni
830:/* some UI refinements: added mouse listener and mouse motion listener to table,
831:/* so the tabbed pane of complex catalogs will be set to show the column under
832:/* mouse point, and the text area in the message display given focus.
833:/*
834:/* Revision 1.3 2000/12/11 22:36:13 smulloni
835:/* improved support for input of UTF.
836:/*
837:/* Revision 1.2 2000/12/08 05:50:30 smulloni
838:/* fixed MessageCatalogEditor. The spi features are now a special build option,
839:/* and editors are loaded through reflection.
840:/* */
|