From: <hu...@us...> - 2007-04-26 04:54:51
|
Revision: 386 http://svn.sourceforge.net/cishell/?rev=386&view=rev Author: huangb Date: 2007-04-25 21:54:49 -0700 (Wed, 25 Apr 2007) Log Message: ----------- Load the menu layout from default_menu.xml Modified Paths: -------------- trunk/clients/gui/org.cishell.reference.gui.menumanager/src/org/cishell/reference/gui/menumanager/menu/MenuAdapter.java Modified: trunk/clients/gui/org.cishell.reference.gui.menumanager/src/org/cishell/reference/gui/menumanager/menu/MenuAdapter.java =================================================================== --- trunk/clients/gui/org.cishell.reference.gui.menumanager/src/org/cishell/reference/gui/menumanager/menu/MenuAdapter.java 2007-04-26 04:53:38 UTC (rev 385) +++ trunk/clients/gui/org.cishell.reference.gui.menumanager/src/org/cishell/reference/gui/menumanager/menu/MenuAdapter.java 2007-04-26 04:54:49 UTC (rev 386) @@ -15,7 +15,10 @@ import java.util.HashMap; import java.util.Map; +import java.io.File; +import java.io.IOException; + import org.cishell.framework.CIShellContext; import org.cishell.framework.algorithm.AlgorithmFactory; import org.cishell.framework.algorithm.AlgorithmProperty; @@ -24,8 +27,13 @@ import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; @@ -34,7 +42,19 @@ import org.osgi.framework.ServiceReference; import org.osgi.service.log.LogService; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/* + * Bonnie's comments: + * weird, why implements AlgorithmProperty? It does not define any abstract interface. + */ public class MenuAdapter implements AlgorithmProperty { private IMenuManager menuBar; private Shell shell; @@ -43,43 +63,282 @@ private Map algorithmToItemMap; private Map itemToParentMap; private ContextListener listener; + private IWorkbenchWindow window; + /* + * This map holds a pid as a key and the corresponding + * ServiceReference as a value. + */ + private Map pidToServiceReferenceMap; + private Map pidToServiceReferenceMapCopy; + private Document dom; + private static File DirForDefaultMenuXMLFile; + private static String DEFAULT_MENU_FILE_NAME = "default_menu.xml"; + + /* + * The following section specify the tags in the default_menu.xml + */ + private static String TAG_TOP_MENU = "top_menu"; + private static String TAG_MENU = "menu"; + private static String ATTR_TYPE = "type"; + private static String ATTR_NAME = "name"; + private static String ATTR_PID = "pid"; + private static String PRESERVED_GROUP = "group"; + private static String PRESERVED_BREAK = "break"; + private static String PRESERVED_EXIT = "Exit"; + private static String PRESERVED_SERVICE_PID="service.pid"; + + public MenuAdapter(IMenuManager menu, Shell shell, - BundleContext bContext,CIShellContext ciContext) { + BundleContext bContext,CIShellContext ciContext, + IWorkbenchWindow window) { this.menuBar = menu; this.shell = shell; this.bContext = bContext; this.ciContext = ciContext; + this.window = window; this.algorithmToItemMap = new HashMap(); this.itemToParentMap = new HashMap(); - + pidToServiceReferenceMap = new HashMap(); + pidToServiceReferenceMapCopy = new HashMap(); + String filter = "(" + Constants.OBJECTCLASS + "=" + AlgorithmFactory.class.getName() + ")"; try { listener = new ContextListener(); bContext.addServiceListener(listener, filter); - initializeMenu(); + preprocessServiceBundles(); + createMenuFromXML(); + processLeftServiceBundles(); + Display.getDefault().asyncExec(updateAction); + +// initializeMenu(); } catch (InvalidSyntaxException e) { getLog().log(LogService.LOG_ERROR, "Invalid Syntax", e); } } - private void initializeMenu() throws InvalidSyntaxException{ + /* + * This method scans all service bundles. If a bundle specifies + * menu_path, get service.pid of this bundle (key), let the service + * reference as the value, and put key/value pair + * to pidToServiceReferenceMap for further process. + */ + private void preprocessServiceBundles() throws InvalidSyntaxException{ ServiceReference[] refs = bContext.getAllServiceReferences( AlgorithmFactory.class.getName(), null); - - if (refs != null) { + if (refs != null){ + for (int i=0; i < refs.length; i++) { + String path = (String)refs[i].getProperty(MENU_PATH); + if (path == null){ + continue; + } + else{ + String pid = (String)refs[i].getProperty(PRESERVED_SERVICE_PID); + System.out.println("pid="+pid); + pidToServiceReferenceMap.put(pid.toLowerCase().trim(), refs[i]); + pidToServiceReferenceMapCopy.put(pid.toLowerCase().trim(), refs[i]); + } + } + } + + } + /* + * Parse default_menu.xml file. For each menu node, get the value of the attribut "pid" + * check if the pid exists in pidToServiceReferenceMap. If so, get the action and add to the parent menu + * If not, ignore this menu. At the end of each top menu or subgroup menu or before help menu, + * add "additions" so that new algorithms can be added on later + */ + private void createMenuFromXML() throws InvalidSyntaxException{ + parseXmlFile(); + //get the root elememt + Element docEle = dom.getDocumentElement(); + //get a nodelist of the top menu elements + NodeList topMenuList = docEle.getElementsByTagName(TAG_TOP_MENU); + if(topMenuList != null && topMenuList.getLength() > 0) { + for(int i = 0 ; i < topMenuList.getLength();i++) { + Element el = (Element)topMenuList.item(i); + processTopMenu(el); + } + } + } + private void processTopMenu (Element topMenuNode){ + MenuManager topMenuBar; + + //First create and add topMenuBar to the menuBar + String topMenuName = topMenuNode.getAttribute(ATTR_NAME); + if (topMenuName.equalsIgnoreCase("file")) + topMenuBar= createMenu("&File", IWorkbenchActionConstants.M_FILE); + else if (topMenuName.equalsIgnoreCase("help")){ + topMenuBar= createMenu("&Help", + IWorkbenchActionConstants.M_HELP); + //allow to append new top leve menu before "Help" + menuBar.add(new GroupMarker(START_GROUP)); + menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + menuBar.add(new GroupMarker(END_GROUP)); + + IWorkbenchAction aboutAction = ActionFactory.ABOUT.create(window); + topMenuBar.add(new Separator()); + topMenuBar.add(aboutAction); + } + else + topMenuBar= createMenu(topMenuName, topMenuName.toLowerCase()); + + menuBar.add(topMenuBar); + + //Second process submenu + processSubMenu(topMenuNode, topMenuBar); + } + + /* + * Recursively process sub menu and group menu + */ + private void processSubMenu (Element menuNode, MenuManager parentMenuBar){ + + NodeList subMenuList = menuNode.getElementsByTagName(TAG_MENU); + if(subMenuList != null && subMenuList.getLength() > 0) { + for(int i = 0 ; i < subMenuList.getLength();i++) { + Element el = (Element)subMenuList.item(i); + + //only process direct children nodes and + //drop all grand or grand of grand children nodes + if (!el.getParentNode().equals(menuNode)) + continue; + + String menu_type = el.getAttribute(ATTR_TYPE); + if (menu_type == null || menu_type.length()==0){ + processAMenuNode(el, parentMenuBar); + } + else if (menu_type.equalsIgnoreCase(PRESERVED_GROUP)){ + String groupName = el.getAttribute(ATTR_NAME); + MenuManager groupMenuBar = new MenuManager(groupName, groupName.toLowerCase()); + parentMenuBar.add(groupMenuBar); + processSubMenu(el, groupMenuBar); + } + else if (menu_type.equalsIgnoreCase(PRESERVED_BREAK)){ + //It seems that Framework automatially takes care of issues + //such as double separators, a separator at the top or bottom + parentMenuBar.add(new Separator()); + } + else if (menu_type.equalsIgnoreCase("preserved")){ + String menuName = el.getAttribute(ATTR_NAME); + if(menuName.equalsIgnoreCase(PRESERVED_EXIT) ){ + //allow to add more menu before "Exit" + if(parentMenuBar.getId().equalsIgnoreCase(IWorkbenchActionConstants.M_FILE)){ + parentMenuBar.add(new GroupMarker(START_GROUP)); + parentMenuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + parentMenuBar.add(new GroupMarker(END_GROUP)); + } + IWorkbenchAction exitAction = ActionFactory.QUIT.create(window); + parentMenuBar.add(exitAction); + } + } + } + //allow to append new submenu(s) at the bottom under each top menu + //except "File" and "Help" + if(!parentMenuBar.getId().equalsIgnoreCase(IWorkbenchActionConstants.M_FILE)&& + !parentMenuBar.getId().equalsIgnoreCase(IWorkbenchActionConstants.M_HELP)) + { + parentMenuBar.add(new GroupMarker(START_GROUP)); + parentMenuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); + parentMenuBar.add(new GroupMarker(END_GROUP)); + } + } + } + + /* + * process a menu (algorithm) + */ + private void processAMenuNode(Element menuNode, MenuManager parentMenuBar ){ + String menuName = menuNode.getAttribute(ATTR_NAME); + String pid = menuNode.getAttribute(ATTR_PID); +// System.out.println(">>>pid="+pid); + if (pid == null || pid.length()==0){ + //check if the name is one of the preserved one + //if so add the default action + + } + else{ + //check if the pid has registered in pidToServiceReferenceMap + if (pidToServiceReferenceMapCopy.containsKey(pid.toLowerCase().trim())){ + ServiceReference ref = (ServiceReference) pidToServiceReferenceMapCopy. + get(pid.toLowerCase().trim()); + pidToServiceReferenceMap.remove(pid.toLowerCase().trim()); + AlgorithmAction action = new AlgorithmAction(ref, bContext, ciContext); + action.setId(getItemID(ref)); + action.setText(menuName); + parentMenuBar.add(action); + } + else{ + //otherwise log the error + getLog().log(LogService.LOG_WARNING, + "Can not find an algorithm package associated with Menu: " + +menuName+" and pid: " +pid+ ". Skip to show it on the menu."); + } + } + } + + private void parseXmlFile(){ + //get the factory + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + try { + //Using factory get an instance of document builder + DocumentBuilder db = dbf.newDocumentBuilder(); + + //parse using builder to get DOM representation of the XML file + if (DirForDefaultMenuXMLFile == null) { + DirForDefaultMenuXMLFile = new File(System.getProperty("user.dir") + File.separator + "configuration"); + } + String fullpath=DirForDefaultMenuXMLFile.getPath()+File.separator+DEFAULT_MENU_FILE_NAME; +// System.out.println(">>parse file: "+fullpath); + dom = db.parse(fullpath); + + }catch(ParserConfigurationException pce) { + pce.printStackTrace(); + }catch(SAXException se) { + se.printStackTrace(); + }catch(IOException ioe) { + ioe.printStackTrace(); + } + } + + /* + * Handle some service bundles that have specified the menu_path and label + * but not specified in the default_menu.xml + */ + private void processLeftServiceBundles(){ + if (!pidToServiceReferenceMap.isEmpty()){ + Object[] keys = pidToServiceReferenceMap.keySet().toArray(); + for (int i=0; i<keys.length; i++){ + ServiceReference ref= (ServiceReference) + pidToServiceReferenceMap.get((String)keys[i]); + makeMenuItem(ref); + } + + } + + } +/* + private void initializeMenu() throws InvalidSyntaxException{ + ServiceReference[] refs = bContext.getAllServiceReferences( + AlgorithmFactory.class.getName(), null); + + if (refs != null) { for (int i=0; i < refs.length; i++) { makeMenuItem(refs[i]); } } - } + + } +*/ private class ContextListener implements ServiceListener { public void serviceChanged(ServiceEvent event) { switch (event.getType()) { case ServiceEvent.REGISTERED: + System.out.println(">>>receive ServiceEvent.Registered"); makeMenuItem(event.getServiceReference()); break; case ServiceEvent.UNREGISTERING: @@ -143,7 +402,7 @@ }; private String getItemID(ServiceReference ref) { - return ref.getProperty("PID:" + Constants.SERVICE_PID) + "-SID:" + + return ref.getProperty("PID:" + Constants.SERVICE_PID) + "-SID:" + ref.getProperty(Constants.SERVICE_ID); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |