Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/merlotxml/merlot/GD_XMLEditorDocUI.java


1   package org.merlotxml.merlot;
2   
3   import java.io.*;
4   import java.awt.*;
5   import java.awt.datatransfer.*;
6   import java.awt.event.*;
7   import java.awt.print.*;
8   import java.util.*;
9   import java.beans.*;
10  import java.lang.reflect.*;
11  
12  import org.w3c.dom.*;
13  
14  import javax.swing.*;
15  import javax.swing.border.*;
16  import javax.swing.event.*;
17  import javax.swing.table.*;
18  import javax.swing.tree.*;
19  
20  import com.sun.javax.swing.*;
21  
22  import org.merlotxml.util.xml.*;
23  import matthew.awt.StrutLayout;
24  import org.merlotxml.awt.*;
25  import org.merlotxml.merlot.plugin.dtd.*;
26  
27  import org.gendiapo.editor.*;
28  import org.gendiapo.editor.document.*;
29  
30  import org.swing.*;
31  
32  /**
33   *
34   * XML Document UI L&F code
35   *
36   * @version $Id: GD_XMLEditorDocUI.java,v 1.39 2002/10/29 15:22:02 flament Exp $
37   *
38   */
39  public class GD_XMLEditorDocUI extends XMLEditorDocUI
40      implements MerlotConstants, ChangeListener, StatusListener, GD_MerlotDOMNodeViewListener
41  {
42      
43      JSplitPane            _workspace;
44  
45      // GD_MerlotDOMNodeViewer
46      Hashtable             _views;
47  
48      StateAction[]         _actions;
49  
50      MerlotDOMNode         _wishNode;
51      
52      AutoHideAttribute     _autoHideAttribute;
53              
54      public GD_XMLEditorDocUI(XMLEditorDoc doc)
55      {
56    super(doc);
57      }    
58      
59      protected void finalize() throws Throwable {
60          _autoHideAttribute.haltNow();
61          super.finalize();        
62      }
63      
64      /**
65       * return action define in dtd plugin for this document
66       */
67      public StateAction[] getActions() {
68    return _actions;
69      }
70  
71      /**
72       * create all view and add them this
73       * @param root the root element in curent document
74       */
75      protected void setupViews(MerlotDOMNode root) {
76    // Creation des vues
77    GD_MerlotDOMNodeViewer styledView    = new GD_StyledView(this, root);
78    GD_MerlotDOMNodeViewer treeView      = new GD_TreeView(this, root);
79    GD_MerlotDOMNodeViewer attributeView = new GD_AttributeView(this, root);
80    GD_MerlotDOMNodeViewer toolbarView   = new GD_ToolbarView(this, root);
81    _views.put("tree",      treeView);
82    _views.put("attribute", attributeView);
83    _views.put("styled",    styledView);
84    _views.put("toolbar",   toolbarView);
85    
86    _actions = ((GD_ToolbarView)toolbarView).getActions();
87    _table = ((GD_TreeView)treeView).getTreeTable();
88    
89    // init _workspace : _scrollPane & _attributeView
90    _workspace = new JSplitPane(JSplitPane.VERTICAL_SPLIT, styledView.getPanel(), attributeView.getPanel());
91    // button to expand or colapse JSplitPane
92    _workspace.setOneTouchExpandable(true);  
93    // Define in percent a height 
94    _workspace.setDividerLocation (0.70);
95    _workspace.setResizeWeight (1.0);
96    _workspace.setPreferredSize(new Dimension(500,380));
97    // the minimum has to be set if the split pane is gonna move
98    _workspace.setMinimumSize(new Dimension(10,10));        
99    
100   // _splitPane
101   _splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeView.getPanel(), _workspace);
102   _splitPane.setOneTouchExpandable(true);
103   _splitPane.setResizeWeight(0.20);
104          
105   this.setLayout(new BorderLayout());
106   this.add(_splitPane, BorderLayout.CENTER);       
107     }
108     
109     protected void setupAutoHideAttribute() {                        
110         GD_MerlotDOMNodeViewer view = (GD_MerlotDOMNodeViewer) _views.get("attribute");
111         JPanel panel = view.getPanel();
112         _autoHideAttribute = new AutoHideAttribute();
113         _autoHideAttribute.lock();
114         panel.addMouseListener(_autoHideAttribute);
115         panel.addMouseMotionListener(_autoHideAttribute);
116         Thread taha = new Thread(_autoHideAttribute, "AutoHideAttribute");        
117         taha.start();
118     }
119     
120     protected class AutoHideAttribute implements MouseListener, MouseMotionListener, Runnable {
121         
122         boolean firstUnlock = true;
123         boolean lock = false;
124         boolean hide = false;
125         boolean inside = false;
126         boolean haltNow = false;        
127         long lastMove = 0;
128         int normalLocation = 0;
129         
130         public void mouseClicked(java.awt.event.MouseEvent mouseEvent) {
131         }
132         
133         public void mouseEntered(java.awt.event.MouseEvent mouseEvent) {
134             inside = true;            
135             showAttributes();
136         }
137         
138         public void mouseExited(java.awt.event.MouseEvent mouseEvent) {                        
139             Component c = mouseEvent.getComponent();
140             Rectangle rect = c.getBounds();
141             int x = mouseEvent.getX();
142             int y = mouseEvent.getY();
143             if ((x<1) || (y<1) || (x >= rect.width-1) || (y >= rect.height-1)) {  
144                 inside = false;
145             }
146         }
147         
148         public void mousePressed(java.awt.event.MouseEvent mouseEvent) {
149         }
150         
151         public void mouseReleased(java.awt.event.MouseEvent mouseEvent) {
152         }        
153 
154         public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
155         }
156         
157         public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {
158             lock = false;
159             inside = true;
160             lastMove = System.currentTimeMillis();            
161         }
162         
163         public void run() {
164             while (!haltNow) {
165                 // wait 1 sec
166                 try {
167                     Thread.sleep(1000); 
168                 } catch (Exception e) {
169                     haltNow = true;
170                 }            
171                 // test if no move since 5 sec
172                 /*
173                 long now = System.currentTimeMillis();
174                 if ((now-lastMove) > 5000) {
175                     inside = false;
176                 }*/
177                 // hide panel if not inside
178                 if (!inside) {
179                     hideAttributes();
180                 }
181             }
182         }
183         
184         public void haltNow() {
185             haltNow = true;
186         }
187         
188         protected synchronized void showAttributes() {
189             if (hide) {
190                 _workspace.setDividerLocation(normalLocation);            
191                 hide = false;
192             }
193         }
194         
195         protected synchronized void hideAttributes() {
196             if ((!lock) && (!hide)) {
197                 if (firstUnlock) {
198                     firstUnlock = false;
199                     JInfoTip.show(_workspace, Component.CENTER_ALIGNMENT, Component.BOTTOM_ALIGNMENT, MerlotResource.getString(UI,"message.hideattribute"));
200                 }
201                 normalLocation = _workspace.getDividerLocation();
202                 _workspace.setDividerLocation(0.99);            
203                 _workspace.setDividerSize(5);
204                 hide = true;
205             }
206         }
207         
208         protected synchronized void lock() {
209             lock = true;
210         }
211    
212     }
213     
214     protected void showAttributes() {
215         _autoHideAttribute.lock();
216         _autoHideAttribute.showAttributes();
217     }
218     
219     protected void hideAttributes() {
220         _autoHideAttribute.hideAttributes();
221     }
222     
223 
224     /**
225      * This panel looks a little like Windows Explorer. It has a treetable at the left,
226      * a JSplitPane slider in the middle, and then an editing workspace at the right.
227      */
228     protected void setupPanel()
229     {
230   /*
231    * init les deux composants avec dim minimum
232    * obligatoire pour le JSplitPane
233    * pour répartir, utiliser setDividerLocation et setResizeWeight
234    */
235 
236   // -- Vues
237   _views = new Hashtable();
238 
239   _XMLmodel = _doc.getTreeTableModel();
240   MerlotDOMDocument   root = _XMLmodel.getDocument();
241   MerlotDOMNode[] children = root.getChildNodes();  
242   MerlotDOMNode visualroot = children[1];  
243   setupViews(visualroot);
244         setupAutoHideAttribute();
245   
246   // Ajout de this comme listener des MerlotDOMNodeViewer
247   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {
248       GD_MerlotDOMNodeViewer mdnv = (GD_MerlotDOMNodeViewer) (e.nextElement());
249       mdnv.addMerlotDOMNodeViewListener(this);
250   }
251   
252   // -- StatusPanel
253         _statusPanel = new JPanel();
254         PercentLayout  statusLay = new PercentLayout(PercentLayout.HORIZONTAL, 5);
255         // statusLay.DEBUG = true;
256   
257         _statusPanel.setLayout(statusLay);
258     
259         _status1 = new JLabel();
260     
261         _status2 = new JLabel();
262         _status2.setPreferredSize(new Dimension(100,20));
263 
264         _status3 = new JLabel();
265         _statusPanel.add(_status1,new PercentLayout.Constraints(60,PercentLayout.BOTH));
266         _statusPanel.add(_status2,new PercentLayout.Constraints(10,PercentLayout.BOTH));
267         _statusPanel.add(_status3,new PercentLayout.Constraints(30,PercentLayout.BOTH));  
268     }
269 
270     // --
271     public GD_XMLEditorDoc getXMLEditorDoc() {
272   return (GD_XMLEditorDoc) _doc;
273     }
274     
275     /**
276      * Get JEditorPane of styled view
277      */
278     public JEditorPane getEditorPane() {
279   GD_StyledView styledView = (GD_StyledView) _views.get("styled");
280   return styledView.getEditorPane();
281     }
282     
283     public Printable getPrintable() {
284         return (Printable) getEditorPane();
285     }
286 
287     /**
288      * Update styled view from MerlotDOMDocument
289      */
290     public void updateStyledView() {
291   GD_StyledView styledView = (GD_StyledView) _views.get("styled");
292   styledView.updateStyledView();
293     }
294     
295     /**
296      * Save the current node from view
297      */
298     public boolean sync() {  
299   boolean allSync = true;
300   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {      
301       GD_MerlotDOMNodeViewListener mdnv = (GD_MerlotDOMNodeViewListener) (e.nextElement());     
302       if (!mdnv.beforeSelect(null,null)) {
303     allSync = false;
304       }
305   }
306   return allSync;  
307     }
308 
309     /**
310      * Propagate beforeSelect to all view expect from "view"
311      * @param view the view which want to change node
312      * @param newNode the node selected in view
313      */
314     public boolean beforeSelect(GD_MerlotDOMNodeViewer view, MerlotDOMNode newNode) {
315   // Make Selection for all view expect for "view"
316   boolean ok = true;
317   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {      
318       GD_MerlotDOMNodeViewListener mdnv = (GD_MerlotDOMNodeViewListener) (e.nextElement());     
319       if (mdnv != view) {
320     if (!mdnv.beforeSelect(view,newNode)) {
321         ok = false;
322     }
323       }
324   }
325   return ok;
326     }
327 
328     /**
329      * Select the node than the current node in "view"
330      * @param view the view of reference
331      */
332     public void selected(GD_MerlotDOMNodeViewer view) {
333   MerlotDOMNode node = view.getNode();
334   
335   // Supprime this des listener pour chaque vue
336   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {
337       GD_MerlotDOMNodeViewer mdnv = (GD_MerlotDOMNodeViewer) (e.nextElement());
338       mdnv.removeMerlotDOMNodeViewListener(this);
339   }
340     
341   // Selection pour toutes les autres vue que view
342   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {
343       GD_MerlotDOMNodeViewer mdnv = (GD_MerlotDOMNodeViewer) (e.nextElement());
344       if (mdnv != view) {
345     mdnv.select(node);
346       }
347   }
348 
349   // Remet this comme listener pour chaque vue
350   for (Enumeration e = _views.elements() ; e.hasMoreElements() ;) {
351       GD_MerlotDOMNodeViewer mdnv = (GD_MerlotDOMNodeViewer) (e.nextElement());
352       mdnv.addMerlotDOMNodeViewListener(this);
353   }
354 
355   updateNodeMenu(XMLEditorFrame.getSharedInstance()._nodeMenu);
356     }
357     
358     /**
359      * return the node that GD_XMLEditorDoc want to show
360      */
361     private MerlotDOMNode getWishNode() {
362   return _wishNode;
363     }
364   
365     /**
366      * call from GD_XMLEditorDoc 
367      * @param node the node that GD_XMLEditorDoc want to edit
368      * @param brandSpankinNew not used
369      */
370     public void editNode(MerlotDOMNode node, boolean brandSpankinNew) {
371   _wishNode = node;
372     }
373 
374     /**
375      * override default to do nothing
376      */
377     public void selectNode(MerlotDOMNode node) {
378   //editNode(node, false);
379     }
380 
381     /**
382      * select a node
383      * in fact select a node in first view then all view are synchronize
384      * @param node the node to select
385      */
386     public void syncSelectNode(MerlotDOMNode node) {
387   Enumeration e = _views.elements();
388   GD_MerlotDOMNodeViewer first = (GD_MerlotDOMNodeViewer) e.nextElement();
389   first.select(node);
390     }
391 
392     class AsyncSelect implements Runnable {
393   
394   MerlotDOMNode _node;
395   
396   public AsyncSelect(MerlotDOMNode node) {
397       _node = node;
398   }
399   
400   public void run() {
401       syncSelectNode(_node);
402   }
403     }    
404     
405     /**
406      * call syncSelectNode with SwingUtilities.invokeLater
407      */
408     public void asyncSelectNode(MerlotDOMNode node) {
409   SwingUtilities.invokeLater(new AsyncSelect(node));
410     }
411     
412     /**
413      * override default to do nothing
414      */
415     public void refreshNode(MerlotDOMNode node, boolean cancelOnly) {
416   //editNode(node, false);
417     }
418 
419     /**
420      * override default to do nothing
421      */
422     public void showNode(MerlotDOMNode node) {
423   //editNode(node, false);
424     
425     }
426         
427     /**
428      * call from GD_XMLEditorDoc to select another node when the deleted one
429      * @param node the node that was deleted
430      */
431     public void deleteNode(MerlotDOMNode node) {
432   MerlotDOMNode select = node.getPreviousSibling();
433 
434   while (select==null?false:((select instanceof MerlotDOMText)?(!((MerlotDOMText) select).isVisible()):false)) {
435       select = select.getPreviousSibling();
436   }
437   
438   if (select == null) {
439       select = node.getParentNode();
440   }
441 
442   if (node != null) {
443       asyncSelectNode(select);
444   }
445     }
446     
447     /**
448      * return the current select node (use the first view)
449      */
450     public MerlotDOMNode getSelectedNode() {
451   GD_MerlotDOMNodeViewer v = (GD_MerlotDOMNodeViewer) _views.elements().nextElement();
452   return v.getNode();
453     }
454 
455     /**
456      * return all nodes selected (for compatibilty : only one can selected)
457      */
458     public MerlotDOMNode[] getSelectedNodes() {
459   MerlotDOMNode[] nodes = new MerlotDOMNode[1];
460   nodes[0] = getSelectedNode();
461   return nodes;
462     }
463    
464     /**
465      * return context menu for "node"
466      * @param node the node of reference to get the context menu
467      */
468     protected java.util.List getNodeMenuItems(MerlotDOMNode node)
469     {
470   ArrayList result = new ArrayList();
471   XMLEditorActions actions = XMLEditorActions.getSharedInstance();
472         Object[] path = _XMLmodel.getTreePathForNode(node);
473     
474         result.add(getNodeAddMenu(node,AFTER));
475         result.add(getNodeAddMenu(node,INTO));
476               
477         result.add(MerlotUtils.createActionMenuItem(_doc._deleteNodeAction));
478 
479         _doc._deleteNodeAction.setEnabled(path.length > 2); // BUG01136
480   _doc._cutNodeAction.setEnabled(path.length > 2);
481   result.add(new Object()); // separator
482 
483         result.add(MerlotUtils.createActionMenuItem(_doc._cutNodeAction));
484         result.add(MerlotUtils.createActionMenuItem(_doc._copyNodeAction));
485         result.add(createTreePasteMenu());
486     
487         enablePasteItems(node);
488   
489         try {
490       MerlotDOMEditor editor = node.getEditor();
491             
492             JMenuItem[] menu_additions = editor.getMenuItems(node);
493             if (menu_additions != null && menu_additions.length > 0) {
494     result.add(new Object()); // separator
495 
496                 for (int i = 0; i < menu_additions.length; i++) {
497                     result.add(menu_additions[i]);
498                 }
499       
500             }
501         }
502         catch (Throwable t) {
503             MerlotDebug.exception(t);
504         }
505   return result;
506   
507     }
508     
509     protected void addItemsToMenu(java.util.List menuItems, MenuElement menu)
510     {
511   Iterator iter = menuItems.iterator();
512   while (iter.hasNext()) {
513       Object o = iter.next();
514       if (menu instanceof JMenu) {
515     if (o instanceof JMenuItem) {
516         ((JMenu)menu).add((JMenuItem)o);
517     }
518     else {
519         ((JMenu)menu).addSeparator();
520     }
521       }
522       else if (menu instanceof JPopupMenu) {
523     if (o instanceof JMenuItem) {
524         ((JPopupMenu)menu).add((JMenuItem)o);
525     }
526     else {
527         ((JPopupMenu)menu).addSeparator();
528     }
529       }
530       
531   }
532   
533   
534     }
535     
536       
537     /**
538      * Creates the add-> menu popup for right-click actions on a particular node.
539      *
540      * @param node the node this is acting on.
541      * @param where what the add is for.. INTO, BEFORE, AFTER the context node
542      * @return a menu containing elements that can be added to a node. If the INTO param is
543      * passed, this also adds the add after and before submenus.
544      */
545 
546     protected JMenu getNodeAddMenu(MerlotDOMNode node, int where)
547     {        
548         MerlotDOMNode parent = node.getParentNode();
549         MerlotDOMEditor editor = null;
550         MerlotDOMNode contextNode = null;
551         int contextLocation = -1;
552         
553         String wherestr;
554 
555         JMenu menu;
556         switch (where) {
557         case INTO:
558         default:
559             menu = new GD_JMoreMenu(MerlotResource.getString(UI,"node.popup.add.child"));
560             editor = node.getEditor();
561             contextNode = node;
562             parent = node;
563             wherestr = "INTO";
564             
565             break;
566         case BEFORE:
567             menu = new GD_JMoreMenu(MerlotResource.getString(UI,"node.popup.add.before"));
568             if (parent != null) {
569                 editor = parent.getEditor();
570                 contextNode = parent;
571                 contextLocation = parent.getChildIndex(node);
572             }
573             wherestr = "BEFORE";
574             break;
575         case AFTER:
576             menu = new GD_JMoreMenu(MerlotResource.getString(UI,"node.popup.add.after"));
577             if (parent != null) {
578                 editor = parent.getEditor();
579                 contextNode = parent;
580                 contextLocation = parent.getChildIndex(node) + 1;
581             }
582             wherestr = "AFTER";
583             break;
584         }
585 
586   if (contextNode == null) {
587       menu.setEnabled(false);
588       return menu;
589   }
590         
591         // get list of possible sub-elements for the node here
592         Enumeration elements;
593 
594 
595   if (contextLocation < 0) {
596       elements = contextNode.getAppendableElements();
597   }
598   else {      
599       elements = contextNode.getInsertableElements(contextLocation);
600   }
601         
602   if (elements != null) {
603             // Make list of visible element in menu
604       TreeSet list = new TreeSet();
605             while (elements.hasMoreElements()) {
606                 DTDElement el = (DTDElement) elements.nextElement();
607                 if (!suppressToUser(editor, parent, el)) {
608                     list.add(el);
609                 }
610             }
611             
612             // Find group
613             Collection items = organizeDTDElement(node, list);
614             
615             // Create menu                        
616             ActionListener listener = new NodeAddActionListener(parent,node,where);
617       StringBuffer shortcuts = new StringBuffer();
618             boolean addShortCut = (where == AFTER);
619                         
620             Iterator it = items.iterator();
621             while (it.hasNext()) {
622                 Object o = it.next();
623                 if (o instanceof String) {
624                     String s = (String) o;
625                     menu.add(new JTextSeparator(s));
626                 } else if (o instanceof DTDElement) {
627                     DTDElement el = (DTDElement) o;
628                     
629                     JMenuItem item = DTDElementToJMenuItem(editor, node, el, addShortCut, shortcuts);
630                     item.addActionListener(listener);
631                     item.setActionCommand(el.getName());
632                     menu.add(item);
633                 }
634             }
635   }
636   
637   //menu.addSeparator();
638   //JMenuItem addSpecial = getNodeAddSpecialMenu(node);
639   //menu.insertStatic(addSpecial);
640   if (menu.getItemCount() == 0) {
641       menu.setEnabled(false);
642   }
643         return menu;
644   
645     }          
646     
647     /** Get list of DTDElement and organize it with groups define in plugin
648      * @param elements collection of DTDElement
649      * @return collection of (DTDElement and String), String represents header of groups
650      */
651     public Collection organizeDTDElement(MerlotDOMNode node, Collection elements) {        
652         // Get groups(key=group name, value=list of element name)
653         HashMap groups;
654         java.util.List groupsOrder;
655         Collection result = new ArrayList();        
656         
657         DTDPluginConfig dpc = node.getDTDPluginConfig();
658         if (!(dpc instanceof GD_DTDPluginConfig)) {
659             result = elements;
660         } else {
661             groups = ((GD_DTDPluginConfig) dpc).getGroups();
662             groupsOrder = ((GD_DTDPluginConfig) dpc).getGroupsOrder();
663             
664             if (groupsOrder.isEmpty()) {
665                 result = elements;
666             } else {
667                 // To help to find DTDElement
668                 HashMap nameToDTDElement = new HashMap();
669                 Iterator elementsIterator = elements.iterator();
670                 while (elementsIterator.hasNext()) {
671                     DTDElement dtdelement = (DTDElement) elementsIterator.next();
672                     nameToDTDElement.put(dtdelement.getName(), dtdelement);
673                 }
674                 
675                 // Fill result : process each group
676                 Iterator i = groupsOrder.iterator();
677                 while (i.hasNext()) {
678                     // for one group
679                     String groupName = (String) i.next();
680                     java.util.List groupElements = (java.util.List) groups.get(groupName);
681                     
682                     // add DTDElement of elements
683                     Collection elementsInGroup = new ArrayList();
684                     Iterator ei = groupElements.iterator();
685                     while (ei.hasNext()) {
686                         String element = (String) ei.next();
687                         DTDElement dtdElement = (DTDElement) nameToDTDElement.get(element);
688                         if (dtdElement != null) {
689                             elements.remove(dtdElement);
690                             elementsInGroup.add(dtdElement);
691                         }
692                     }
693                     
694                     // if there is elements in this group add them to the result
695                     if (!elementsInGroup.isEmpty()) {
696                         result.add(groupName);
697                         result.addAll(elementsInGroup);
698                     }
699                 }
700                 
701                 // Add no name group
702                 if (!elements.isEmpty()) {
703                     Collection tmp = new ArrayList();
704                     tmp.addAll(elements);
705                     tmp.addAll(result);
706                     result = tmp;
707                 }
708             }
709         }
710         return result;
711     }    
712     
713     protected boolean suppressToUser(MerlotDOMEditor editor, MerlotDOMNode node, DTDElement el) {
714         boolean suppressItems = XMLEditorSettings.getSharedInstance().getSuppressAddMenuItems();        
715         if (!suppressItems) {
716             return false;
717         } else {
718             DTDCacheEntry dtdentry = _doc.getDTDCacheEntry();
719             DTDPluginConfig pluginConfig = null;
720             
721             if (dtdentry instanceof PluginDTDCacheEntry) {
722                 pluginConfig = ((PluginDTDCacheEntry)dtdentry).getPluginConfig();
723             }            
724             MerlotDOMEditor e = null;
725             try {
726                 e = MerlotEditorFactory.getInstance().getEditor(el.getName(),pluginConfig);
727             }
728             catch (InstantiationException ex) {}
729             catch (IllegalAccessException ex) {}
730             
731             if (e == null) {
732                 return false;
733             } else {           
734                 boolean editorSuppress;
735                 boolean eSuppress;
736                 if (editor instanceof GenDiapoEditor) {
737                     editorSuppress = ((GenDiapoEditor) editor).suppressAddType(node, el);
738                 } else {
739                     editorSuppress = editor.suppressAddType(el);
740                 }
741                 if (e instanceof GenDiapoEditor) {
742                     eSuppress = ((GenDiapoEditor) e).suppressAddType(node, el);
743                 } else {
744                     eSuppress = e.suppressAddType(el);
745                 }
746                 return (editorSuppress || eSuppress);
747             }
748         }
749     }
750     
751     protected JMenuItem DTDElementToJMenuItem(MerlotDOMEditor editor, MerlotDOMNode node, DTDElement el, boolean addShortCut, StringBuffer shortcuts) {                
752         // icon
753         Icon icon = null;
754         DTDPluginConfig config = _doc.getDTDPluginConfig();
755         if (config != null) {
756             icon = config.getIconFor(el.getName(), DTDPluginConfig.ICON_SIZE_SMALL);
757         }
758         
759         // text
760         String menuText;
761         if (editor instanceof GenDiapoEditor) {
762             menuText = ((GenDiapoEditor) editor).getUserName(node, el);
763         } else {
764             menuText = el.getName();
765         }
766         
767         // jmenuitem
768         JMenuItem item = new JMenuItem(menuText,icon);                
769         
770         // Add shortcut if necessary
771         if (addShortCut) {
772             
773             // possible char for a shortcut
774             String keys = el.getName().toUpperCase()+"123456789";
775             
776             // delete unwanted character
777             char[] charKeys = keys.toCharArray();
778             keys = "";
779             int i = 0;
780             while (i<charKeys.length) {
781                 char c = charKeys[i++];
782                 if ((c>='A' && c<='Z') || (c>='0' && c<='9')) {
783                     keys += c;
784                 }
785             }
786             
787             // try to find short cut
788             i=0;
789             String shortcutsStr = shortcuts.toString();
790             while ((i<keys.length()) && (shortcutsStr.indexOf(keys.charAt(i))) != -1) {
791                 i++;
792             }
793             
794             // if we found a shortcut add it
795             if (i<keys.length()) {
796                 char key = keys.charAt(i);
797                 shortcuts.append(key);
798                 item.setAccelerator(KeyStroke.getKeyStroke(key, java.awt.event.InputEvent.ALT_MASK));
799             }
800         }
801         
802         return item;
803     }
804 
805     protected void doPopup(MouseEvent e) 
806     {
807   // La source doit provenir d'un Component representant un GD_MerlotDOMNodeViewer
808                
809         JPopupMenu menu = null;
810   
811   Object o = e.getSource();
812 
813   // La source dans etre un composant
814   if (!(o instanceof Component)) {
815       return;
816   } 
817 
818   // Trouve le 1er JPanel parent
819   Component c = (Component) o;
820   int x,y;
821   while ((!(c instanceof JPanel)) || (c == null)) {
822       c = c.getParent();
823       // translate source point
824       e.translatePoint((int)c.getX(), (int)c.getY());
825       if (c instanceof JScrollPane) {    
826     Point p = ((JScrollPane)c).getViewport().getViewPosition();
827     e.translatePoint((int)-p.getX(), (int)-p.getY());
828       }
829   }
830 
831         Point pt = e.getPoint();
832 
833   if (c == null) {
834       return;
835   }
836   JPanel panel = (JPanel) c;      
837 
838   // Recupere la vue associee
839   GD_MerlotDOMNodeViewer viewer = (GD_MerlotDOMNodeViewer) panel.getClientProperty(GD_MerlotDOMNodeViewer.VIEWER);
840 
841   // Recupere le noeud associe
842         MerlotDOMNode node = viewer.getNode();
843 
844   // Creation du menu
845         if (node != null) {
846             menu = getNodePopupMenu(node);
847         }
848     
849   // Placement du menu
850         if (menu != null) {
851             //XXX make sure menu is all the way on the screen
852             menu.pack();
853             Dimension menusize = menu.getPreferredSize();
854             MerlotDebug.msg("menusize = ["+menusize.width+", "+menusize.height+"]  pt.x = "+pt.x+"  pt.y = "+pt.y);
855     
856             Point screenpoint = (Point)pt.clone();
857 
858             javax.swing.SwingUtilities.convertPointToScreen(screenpoint,panel);
859             Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
860 
861             Point endpoint = new Point();
862             endpoint.x = screenpoint.x + menusize.width;
863             endpoint.y = screenpoint.y + menusize.height;
864 
865             if (screenpoint.x < 0) {
866                 screenpoint.x = 0;
867             }
868             if (screenpoint.y < 0) {
869                 screenpoint.y = 0;
870             }
871             if (endpoint.x > (int)screensize.getWidth()) {
872                 screenpoint.x = (int)screensize.getWidth() - menusize.width;
873             }
874             if (endpoint.y > (int)screensize.getHeight()) {
875                 // Add 30 points for a possible Windows Taskbar
876                 // (i.e. - programmer couldn't figure out how to ask the system
877                 // if it was auto-hidden.) - empirically determined value 
878                 // if anybody has a better idea.....
879                 screenpoint.y = (int)screensize.getHeight() - menusize.height - 30;
880             }
881 
882             Point componentpoint = (Point)screenpoint.clone();
883             javax.swing.SwingUtilities.convertPointFromScreen(componentpoint,panel);
884             pt = componentpoint;                   
885             menu.show(panel,pt.x,pt.y);
886         }
887           
888         //  MerlotDebug.msg("node = "+node+ " real node class = " +node.getRealNode().getClass());    
889     
890     }
891 
892     // --
893     public Transferable getTransferable() 
894     {
895         GD_TreeView treeView = (GD_TreeView) _views.get("tree");
896   return treeView.getTransferable();
897     }  
898 
899     public int getSelectedRow() 
900     {
901         GD_TreeView treeView = (GD_TreeView) _views.get("tree");
902         return treeView.getSelectedRow();
903     }
904 
905     // --
906     public void stateChanged(ChangeEvent evt)
907     {
908         MerlotDebug.msg("stateChanged. MouseChagnedTab = "+_mouseChangedTab);
909   
910         /*=$**/
911   //aucun composant sélectionné
912   //Component c = _workspace.getSelectedComponent();
913   Component c = null;
914   /*=$**/
915         
916   if (c != null && _mouseChangedTab) {
917       // find the component in the hashtable
918             Object o = _openEditors.get(c);
919             if (o instanceof MerlotDOMNode) {
920     // hilight the path to this node in the tree
921                 Object[] path = _XMLmodel.getTreePathForNode((MerlotDOMNode)o);
922                 _table.getTree().setSelectionPath(new TreePath(path));
923             }
924         }
925     }
926   
927 
928 
929     protected class NodeAddActionListener implements ActionListener /*XMLEditorDocUI.NodeAddActionListener*/ {
930 
931         MerlotDOMNode _parent, _sibling;
932   int _action = INTO;        
933   
934         public NodeAddActionListener (MerlotDOMNode parent) {
935             _parent = parent;
936   }
937 
938         public NodeAddActionListener (MerlotDOMNode parent, MerlotDOMNode sibling, int action) {
939             _parent = parent;
940             _sibling = sibling;
941             _action = action;            
942   }
943 
944         public void actionPerformed(ActionEvent evt) {      
945       if (sync()) {
946       
947     Object source = evt.getSource();
948     if (source instanceof JMenuItem) {
949         String s = evt.getActionCommand();
950         MerlotDebug.msg("Add: "+s);
951         // create an element
952         // update of wishNode
953         _doc.addNewNode(_parent, s, _sibling, _action); 
954         // select wishNode
955         asyncSelectNode(getWishNode());                    
956     }
957       }
958   }
959 
960     }
961         
962     boolean isThereElement(MerlotDOMNode[] nodes) {
963   for(int i=0; i<nodes.length; i++) {
964       if (nodes[i] instanceof MerlotDOMElement) {
965     return true;
966       }
967   }
968   return false;
969     }
970   
971     public void statusChanged(StatusEvent evt) {
972     }
973 
974     public Transferable getTransferable(MerlotDOMNode node) {
975   Transferable t;
976 
977   Object[] pathToChild = _XMLmodel.getTreePathForNode(node);  
978   TreePath pToChild = new TreePath(pathToChild);
979   TreePath[] treePaths = new TreePath[1];
980   treePaths[0] = pToChild;
981 
982   t = _XMLmodel.getTransferable(treePaths);
983   return t;
984     }
985 
986     public Transferable getTransferableOfChilds(MerlotDOMNode node) {
987   Transferable t;
988   MerlotDOMNode[] children = node.getChildNodes();
989   TreePath[] treePaths = new TreePath[children.length];
990 
991   for (int i=0; i<children.length; i++) {
992       Object[] pathToChild = _XMLmodel.getTreePathForNode(children[i]);
993       treePaths[i] = new TreePath(pathToChild);
994   }
995   
996   t = _XMLmodel.getTransferable(treePaths);
997   return t;
998     }
999 
1000    public void updateNodeMenu(JMenu menu) 
1001    {  
1002  MerlotDOMNode node = getSelectedNode();
1003  java.util.List nodeMenu = getNodeMenuItems(node);
1004  ((GD_XMLEditorFrame) XMLEditorFrame.getSharedInstance()).setupEditMenu(menu, nodeMenu);
1005    }
1006
1007    
1008}