/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.jsf.ui.editor.model.impl; import java.util.*; import java.beans.*; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Control; import org.jboss.tools.common.model.*; import org.jboss.tools.common.model.event.*; import org.jboss.tools.jsf.JSFPreference; import org.jboss.tools.jsf.model.helpers.JSFProcessStructureHelper; import org.jboss.tools.jsf.ui.JsfUiPlugin; import org.jboss.tools.jsf.ui.editor.model.IJSFElement; import org.jboss.tools.jsf.ui.editor.model.IJSFElementList; import org.jboss.tools.jsf.ui.editor.model.IJSFModel; import org.jboss.tools.jsf.ui.editor.model.IJSFModelListener; import org.jboss.tools.jsf.ui.editor.model.IJSFOptions; import org.jboss.tools.jsf.ui.editor.model.ILink; import org.jboss.tools.jsf.ui.editor.model.IGroup; import org.jboss.tools.jsf.ui.editor.model.IPage; import org.jboss.tools.jsf.ui.preferences.JSFFlowTabbedPreferencesPage; import org.jboss.tools.common.model.ui.action.*; import org.jboss.tools.common.model.ui.util.ModelUtilities; import org.jboss.tools.common.model.util.XModelTreeListenerSWTSync; public class JSFModel extends JSFElement implements IJSFModel, PropertyChangeListener, XModelTreeListener { protected List<IJSFModelListener> strutsModelListeners = new Vector<IJSFModelListener>(); protected JSFHashtable map = new JSFHashtable(); protected JSFElementList processItemList = new ProcessItemList(); protected JSFProcessStructureHelper helper = JSFProcessStructureHelper.instance; protected JSFOptions options; protected boolean modified = false; public JSFModel() { try { setName("Struts Model"); } catch (PropertyVetoException ex) { JsfUiPlugin.getPluginLog().logError(ex); } } public void dispose() { this.disconnectFromModel(); if (map != null) map.dispose(); map = null; if (strutsModelListeners != null) strutsModelListeners.clear(); strutsModelListeners = null; if (processItemList != null) processItemList.dispose(); processItemList = null; if (options != null) options.dispose(); options = null; } public boolean isBorderPaint() { return false; } public IJSFOptions getOptions() { return options; } public JSFModel(Object data) { this(); setData(((XModelObject) data).getChildByPath("process")); //$NON-NLS-1$ map.setData((XModelObject) data); } public void updateLinks() { IGroup group; IPage page; for (int i = 0; i < getGroupList().size(); i++) { group = (IGroup) getGroupList().get(i); for (int j = 0; j < group.getPageList().size(); j++) { page = (IPage) group.getPageList().get(j); for (int k = 0; k < page.getLinkList().size(); k++) { ((ILink) page.getLinkList().get(k)).setTarget(); } } } } public Object get(String name) { return null; } public void put(String name, Object value) { } public JSFProcessStructureHelper getHelper() { return helper; } public int getProcessItemCounter() { return processItemList.size(); } public IGroup getGroup(int index) { return (IGroup) processItemList.get(index); } public IGroup getGroup(String groupName) { return (IGroup) processItemList.get(groupName); } public IGroup getGroup(Object source) { IGroup[] is = (IGroup[]) processItemList.elements .toArray(new IGroup[0]); for (int i = 0; i < is.length; i++) if (is[i].getSource() == source) return is[i]; return null; } // Module removers public void removeGroup(String moduleName) { } public void removeGroup(IGroup removeProcessItem) { } public void propertyChange(PropertyChangeEvent pce) { } IGroup selectedGroup = null; public void setSelectedProcessItem(IGroup group) { IGroup oldValue = selectedGroup; selectedGroup = group; propertyChangeSupport.firePropertyChange("selectedProcessItem", //$NON-NLS-1$ oldValue, group); } public IGroup getSelectedProcessItem() { return selectedGroup; } public String getText() { return ""; //$NON-NLS-1$ } XModelTreeListenerSWTSync listener = null; public void setData(Object data) { source = (XModelObject) data; if (source == null) { return; } helper.autolayout(source); map.put(source.getPath(), this); processItemList = new ProcessItemList(source); listener = new XModelTreeListenerSWTSync(this); source.getModel().addModelTreeListener(listener); options = new JSFOptions(); } public void disconnectFromModel() { if (listener != null) { source.getModel().removeModelTreeListener(listener); } if(options != null) { options.disconnectFromModel(); } if(map != null) { map.disconnectFromModel(); } } public boolean isEditable() { return source != null && source.getModelEntity().isEditable(source, "body"); //$NON-NLS-1$ } public boolean areCommentsVisible() { return false; } public boolean isModified() { return modified; } public void setModified(boolean set) { boolean oldValue = modified; modified = set; propertyChangeSupport .firePropertyChange("modified", oldValue, modified); //$NON-NLS-1$ } // ----------------------------------------------------------------------- // fire events // ----------------------------------------------------------------------- public void fireProcessChanged(boolean flag) { if (strutsModelListeners == null) return; List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>(); targets.addAll(strutsModelListeners); for (int i = 0; i < targets.size(); i++) { IJSFModelListener listener = (IJSFModelListener) targets.get(i); if (listener != null) { listener.processChanged(flag); } } setModified(true); } public void fireProcessItemAdd(IGroup newProcessItem) { List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>(); targets.addAll(strutsModelListeners); for (int i = 0; i < targets.size(); i++) { IJSFModelListener listener = (IJSFModelListener) targets.get(i); if (listener != null) { listener.groupAdd(newProcessItem); } } setModified(true); } public void fireProcessItemRemove(IGroup newProcessItem, int index) { List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>(); targets.addAll(strutsModelListeners); for (int i = 0; i < targets.size(); i++) { IJSFModelListener listener = (IJSFModelListener) targets.get(i); if (listener != null) { listener.groupRemove(newProcessItem); } } setModified(true); } public void fireLinkAdd(ILink newLink) { List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>(); targets.addAll(strutsModelListeners); for (int i = 0; i < targets.size(); i++) { IJSFModelListener listener = (IJSFModelListener) targets.get(i); if (listener != null) { listener.linkAdd(newLink); } } setModified(true); } public void fireLinkRemove(ILink newLink) { List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>(); targets.addAll(strutsModelListeners); for (int i = 0; i < targets.size(); i++) { IJSFModelListener listener = (IJSFModelListener) targets.get(i); if (listener != null) { listener.linkRemove(newLink); } } setModified(true); } public void fireElementRemoved(IJSFElement element, int index) { } public void fireElementInserted(IJSFElement element) { } public void addJSFModelListener(IJSFModelListener listener) { strutsModelListeners.add(listener); } public void removeJSFModelListener(IJSFModelListener listener) { if(strutsModelListeners != null) strutsModelListeners.remove(listener); } public void remove() { } public String getIconPath() { return null; } public IGroup addGroup(IGroup group) { return null; } public IGroup addGroup(String group) { return null; } public IGroup addGroup(Object source, int x, int y) { return null; } public IGroup addGroup(IJSFElement element) { return null; } public IJSFElementList getGroupList() { return processItemList; } public void nodeChanged(XModelTreeEvent event) { fireProcessChanged(false); if (map == null || event == null) return; IJSFElement element = (JSFElement) map.get(event.getInfo()); if (element != null && !event.getModelObject().getPath() .equals(event.getInfo())) { updateCash((String) event.getInfo()); } String path = event.getModelObject().getPath(); element = (path == null) ? null : (IJSFElement) map.get(path); if (element == null) { return; } element.nodeChanged(event); } public void structureChanged(XModelTreeEvent event) { JSFElement element; Object obj = event.getModelObject().getPath(); if (obj == null) return; if (map == null) return; element = (JSFElement) map.get(obj); if (element == null) { return; } if (event.kind() == XModelTreeEvent.STRUCTURE_CHANGED) { element.structureChanged(event); } else if (event.kind() == XModelTreeEvent.CHILD_ADDED) { element.nodeAdded(event); } else if (event.kind() == XModelTreeEvent.CHILD_REMOVED) { element.nodeRemoved(event); } } public void putToMap(Object key, IJSFElement value) { getMap().put(key, value); } public void removeFromMap(Object key) { getMap().remove(key); } public IJSFElement getFromMap(Object key) { return getMap().get(key); } public class ProcessItemPropertyChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { IGroup processItem = (IGroup) event.getSource(); if (event.getPropertyName().equals("selected")) { //$NON-NLS-1$ if (((Boolean) event.getNewValue()).booleanValue()) setSelectedProcessItem(processItem); } } } public class ProcessItemList extends JSFElementList { protected ProcessItemList() { } public ProcessItemList(XModelObject processItemSource) { super(JSFModel.this, JSFModel.this.source); if (((XModelObject) JSFModel.this.getSource()).getPath() == null) return; XModelObject[] processItemNodeList = getHelper().getGroups( JSFModel.this.source); for (int i = 0; i < processItemNodeList.length; i++) { IGroup newProcessItem = new Group(JSFModel.this, processItemNodeList[i]); newProcessItem.addPropertyChangeListener("selected", //$NON-NLS-1$ new ProcessItemPropertyChangeListener()); add(newProcessItem); } } public void structureChanged(Object eventData) { } public void nodeAdded(Object eventData) { XModelTreeEvent event = (XModelTreeEvent) eventData; IGroup newProcessItem = new Group(JSFModel.this, ((XModelObject) event.getInfo())); this.add(newProcessItem); fireProcessItemAdd(newProcessItem); } public void nodeRemoved(Object eventData) { XModelTreeEvent event = (XModelTreeEvent) eventData; IJSFElement removedProcessItem = this.getFromMap(event.getInfo()); int index = this.indexOf(removedProcessItem); removedProcessItem.remove(); this.remove(removedProcessItem); this.removeFromMap(((XModelTreeEvent) eventData).getInfo()); fireProcessItemRemove((Group) removedProcessItem, index); clearCash((String) event.getInfo()); } } public JSFHashtable getMap() { return map; } public IJSFElement findElement(String key) { return map.get(key); } public class JSFHashtable implements XModelTreeListener { private Hashtable<Object, IJSFElement> map = new Hashtable<Object, IJSFElement>(); XModelObject source; String name; public void dispose() { disconnectFromModel(); if (map != null) map.clear(); map = null; } public void put(Object key, IJSFElement value) { map.put(key, value); } public void setData(XModelObject data) { source = data; source.getModel().addModelTreeListener(JSFHashtable.this); name = source.getAttributeValue("name"); //$NON-NLS-1$ } public void disconnectFromModel() { source.getModel().removeModelTreeListener(JSFHashtable.this); } public IJSFElement get(Object key) { return map.get(key); } public void remove(Object key) { map.remove(key); } public void nodeChanged(XModelTreeEvent event) { String path; JSFElement element; if (!source.getAttributeValue("name").equals(name)) { //$NON-NLS-1$ name = source.getAttributeValue("name"); //$NON-NLS-1$ Enumeration<Object> keys = map.keys(); while (keys.hasMoreElements()) { Object key = keys.nextElement(); if(!(key instanceof String)) continue; path = (String) key; element = (JSFElement) map.get(path); if (element != null) { if (element.getSource() != null) { map.remove(path); map.put(((XModelObject) element.getSource()) .getPath(), element); } } } } } public void structureChanged(XModelTreeEvent event) { } } protected void clearCash(String path) { updateCash(path, true); } protected void updateCash(String path) { updateCash(path, false); } protected void updateCash(String path, boolean clear) { String rpath = path + "/"; //$NON-NLS-1$ Object[] ks = map.map.keySet().toArray(); for (int i = 0; i < ks.length; i++) { if (!ks[i].equals(path) && !ks[i].toString().startsWith(rpath)) continue; IJSFElement n = (IJSFElement) map.map.get(ks[i]); map.map.remove(ks[i]); if (clear) continue; XModelObject o = (XModelObject) n.getSource(); if (!o.isActive()) continue; map.map.put(o.getPath(), n); } } public Menu getPopupMenu(Control control, Object environment) { if (source == null) return null; if (source.getModelEntity().getActionList().getActionItems().length != 0) { XModelObjectActionList l = new XModelObjectActionList(source .getModelEntity().getActionList(), source, null, environment); Menu menu = l.createMenu(control); return menu; } return null; } public Menu getPopupMenu(Control control) { return getPopupMenu(control, null); } public boolean isConfirmed() { return true; } class JSFOptions implements XModelTreeListener, IJSFOptions { XModelObject optionsObject = ModelUtilities.getPreferenceModel() .getByPath(JSFFlowTabbedPreferencesPage.JSF_EDITOR_PATH); XModelTreeListenerSWTSync optionsListener = new XModelTreeListenerSWTSync( this); Font viewPathFont = null, linkPathFont = null; public JSFOptions() { optionsObject.getModel().addModelTreeListener(optionsListener); } public void dispose() { disconnectFromModel(); if (linkPathFont != null && linkPathFont.isDisposed()) linkPathFont.dispose(); linkPathFont = null; if (viewPathFont != null && viewPathFont.isDisposed()) viewPathFont.dispose(); viewPathFont = null; } public boolean isGridVisible() { String str = optionsObject.getAttributeValue("Show Grid"); //$NON-NLS-1$ if (str.equals("yes")) //$NON-NLS-1$ return true; else return false; } public int getGridStep() { return 8; } public int getVisualGridStep() { String str = optionsObject.getAttributeValue("Grid Step"); //$NON-NLS-1$ return Integer.parseInt(str); } public Font getLinkPathFont() { String name; int size = 8, style = 1; int pos, pos2, pos3; String str = optionsObject.getAttributeValue("Link Path Font"); //$NON-NLS-1$ pos = str.indexOf(","); //$NON-NLS-1$ if (pos < 0) name = str; else { name = str.substring(0, pos); pos2 = str.indexOf("size="); //$NON-NLS-1$ if (pos2 >= 0) { pos3 = str.indexOf(",", pos2); //$NON-NLS-1$ if (pos3 < 0) size = Integer.parseInt(str .substring(pos2 + 5, str.length())); else size = Integer.parseInt(str.substring(pos2 + 5, pos3)); } pos2 = str.indexOf("style="); //$NON-NLS-1$ if (pos2 >= 0) { pos3 = str.indexOf(",", pos2); //$NON-NLS-1$ if (pos3 < 0) style = Integer.parseInt(str.substring(pos2 + 6, str .length())); else style = Integer.parseInt(str.substring(pos2 + 6, pos3)); } } if (linkPathFont == null) { linkPathFont = new Font(null, name, size, style); } else { if (!linkPathFont.getFontData()[0].getName().equals(name) || linkPathFont.getFontData()[0].getHeight() != size || linkPathFont.getFontData()[0].getStyle() != style) { linkPathFont = new Font(null, name, size, style); } } return linkPathFont; } public Font getViewPathFont() { String name; int size = 8, style = 1; int pos, pos2, pos3; String str = optionsObject.getAttributeValue("View Path Font"); //$NON-NLS-1$ pos = str.indexOf(","); //$NON-NLS-1$ if (pos < 0) name = str; else { name = str.substring(0, pos); pos2 = str.indexOf("size="); //$NON-NLS-1$ if (pos2 >= 0) { pos3 = str.indexOf(",", pos2); //$NON-NLS-1$ if (pos3 < 0) size = Integer.parseInt(str .substring(pos2 + 5, str.length())); else size = Integer.parseInt(str.substring(pos2 + 5, pos3)); } pos2 = str.indexOf("style="); //$NON-NLS-1$ if (pos2 >= 0) { pos3 = str.indexOf(",", pos2); //$NON-NLS-1$ if (pos3 < 0) style = Integer.parseInt(str.substring(pos2 + 6, str .length())); else style = Integer.parseInt(str.substring(pos2 + 6, pos3)); } } if (viewPathFont == null) { viewPathFont = new Font(null, name, size, style); } else { if (!viewPathFont.getFontData()[0].getName().equals(name) || viewPathFont.getFontData()[0].getHeight() != size || viewPathFont.getFontData()[0].getStyle() != style) { viewPathFont = new Font(null, name, size, style); } } return viewPathFont; } public void disconnectFromModel() { optionsObject.getModel().removeModelTreeListener(optionsListener); if (optionsListener != null) optionsListener.dispose(); optionsListener = null; } public void nodeChanged(XModelTreeEvent event) { fireProcessChanged(false); Group group; for (int i = 0; i < getGroupList().size(); i++) { group = (Group) getGroupList().get(i); group.fireGroupChange(); for (int j = 0; j < group.getListOutputLinks().size(); j++) { ((Link) group.getListOutputLinks().get(j)).fireLinkChange(); } } } public void structureChanged(XModelTreeEvent event) { //fireProcessChanged(false); } public boolean switchToSelectionTool() { String str = JSFPreference.ENABLE_CONTROL_MODE_ON_TRANSITION_COMPLETED .getValue(); if (str != null && str.equals("yes")) //$NON-NLS-1$ return true; else return false; } public boolean showShortcutIcon() { String str = JSFPreference.SHOW_SHORTCUT_ICON.getValue(); if (str != null && str.equals("yes")) //$NON-NLS-1$ return true; else return false; } public boolean showShortcutPath() { String str = JSFPreference.SHOW_SHORTCUT_PATH.getValue(); if (str != null && str.equals("yes")) //$NON-NLS-1$ return true; else return false; } } }