/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.inspector; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Observable; import java.util.Observer; import java.util.StringTokenizer; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JMenuBar; import org.openflexo.inspector.model.InspectorMapping; import org.openflexo.inspector.model.InspectorModel; import org.openflexo.inspector.model.TabModel; import org.openflexo.inspector.selection.InspectorSelection; import org.openflexo.inspector.selection.UniqueSelection; import org.openflexo.inspector.widget.DenaliWidget; import org.openflexo.localization.FlexoLocalization; import org.openflexo.xmlcode.StringEncoder; import org.openflexo.xmlcode.XMLCoder; import org.openflexo.xmlcode.XMLDecoder; import org.openflexo.xmlcode.XMLMapping; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Controller dedicated to inspector: there is only one instance of this controller * * @author bmangez,sguerin */ public class InspectorController implements Observer, AbstractController { private final Logger logger = Logger.getLogger(InspectorController.class.getPackage().getName()); private Hashtable<String, InspectorModel> _inspectors; private Vector<InspectingWidget> _inspectingWidgets; public final LabelFontMetrics labelFontMetrics = new LabelFontMetrics(DenaliWidget.DEFAULT_LABEL_FONT); private InspectorNotFoundHandler _inspectorNotFoundHandler; private Vector<InspectorExceptionHandler> _exceptionHandlers; protected XMLMapping _inspectorMapping; private InspectorDelegate delegate; private HelpDelegate helpDelegate; private InspectorWidgetConfiguration inspectorConfiguration; private InspectorController _instance; // ========================================================================== // ============================= Constructor // ================================ // ========================================================================== protected InspectorController(InspectorDelegate inspectorDelegate, HelpDelegate helpDelegate) { this(inspectorDelegate, helpDelegate, null); } protected InspectorController(InspectorDelegate inspectorDelegate, HelpDelegate helpDelegate, InspectorWidgetConfiguration inspectorConfiguration) { super(); this.delegate = inspectorDelegate; this.helpDelegate = helpDelegate; this.inspectorConfiguration = inspectorConfiguration; _inspectors = new Hashtable<String, InspectorModel>(); _inspectingWidgets = new Vector<InspectingWidget>(); // _inspectorWindows = new Hashtable<JFrame,InspectorWindow>(); _exceptionHandlers = new Vector<InspectorExceptionHandler>(); } public InspectorController instance() { return _instance; } public void registerAsInstance(InspectorController instance) { _instance = instance; } public boolean hasInstance() { return _instance != null; } public InspectorWindow createInspectorWindow(JFrame frame) { InspectorWindow inspectorWindow = new InspectorWindow(frame, this); _inspectingWidgets.add(inspectorWindow); return inspectorWindow; } public InspectorTabbedPanel createInspectorTabbedPanel() { InspectorTabbedPanel inspectorTabbedPanel = new InspectorTabbedPanel(this); _inspectingWidgets.add(inspectorTabbedPanel); return inspectorTabbedPanel; } public InspectorSinglePanel createInspectorSinglePanel(TabModel tabModel) { InspectorSinglePanel inspectorSinglePanel = new InspectorSinglePanel(this, tabModel); _inspectingWidgets.add(inspectorSinglePanel); return inspectorSinglePanel; } public InspectorWindow createInspectorWindow(JFrame frame, JMenuBar menuBar) { return createInspectorWindow(frame); } public XMLMapping getInspectorMapping() { return InspectorMapping.getInstance(); } public InspectorModel importInspectorFile(File inspectorFile) throws FileNotFoundException { InputStream inputStream = null; try { inputStream = new FileInputStream(inspectorFile); return importInspector(inspectorFile.getName(), inputStream); } catch (FileNotFoundException e) { throw e; } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised during inspector import: " + e + "\nFile path is: " + inspectorFile.getAbsolutePath()); } e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Cannot close inspector input stream '" + inspectorFile.getAbsolutePath() + "'"); } e.printStackTrace(); } } return null; } public InspectorModel importInspector(String name, InputStream stream) { try { if (getInspectorMapping() != null) { InspectorModel inspectorModel = (InspectorModel) XMLDecoder.decodeObjectWithMapping(stream, getInspectorMapping(), this); importInspector(name, inspectorModel); if (logger.isLoggable(Level.FINE)) { if (logger.isLoggable(Level.FINE)) { logger.fine("Getting this " + XMLCoder.encodeObjectWithMapping(inspectorModel, getInspectorMapping(), StringEncoder.getDefaultInstance())); } } return inspectorModel; } } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Exception raised during inspector import '" + name + "': " + e); } e.printStackTrace(); } return null; } public boolean importInspector(String name, InspectorModel inspector) { _inspectors.put(name, inspector); return true; } public boolean updateSuperInspectors() { Iterator<InspectorModel> it = _inspectors.values().iterator(); while (it.hasNext()) { InspectorModel inspector = it.next(); if (inspector.superInspectorName != null) { InspectorModel superInspector = _inspectors.get(inspector.superInspectorName); if (superInspector == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("WARNING : can't find super inspector named :" + inspector.superInspectorName); } } else { inspector.setSuperInspector(superInspector); } } } return true; } // ========================================================================== // ============================= Observer =================================== // ========================================================================== @Override public void update(Observable observable, Object selection) { if (selection instanceof InspectorSelection) { InspectorSelection inspectorSelection = (InspectorSelection) selection; if (inspectorSelection instanceof UniqueSelection) { currentInspectionContext = ((UniqueSelection) inspectorSelection).getInspectionContext(); } for (InspectingWidget i : _inspectingWidgets) { i.newSelection(inspectorSelection); } } } private Hashtable<String, Object> currentInspectionContext; protected Hashtable<String, Object> getCurrentInspectionContext() { return currentInspectionContext; } // ========================================================================== // ============================= Class Methods // ============================== // ========================================================================== public Element elementFromFilePath(String xmlFilePath) throws Exception { return parseXMLFile(xmlFilePath).getDocumentElement(); } public Element elementFromFile(File xmlFile) throws Exception { return parseXMLFile(xmlFile).getDocumentElement(); } public Document parseXMLFile(String xmlFilePath) throws Exception { File f = new File(xmlFilePath); FileInputStream fis = new FileInputStream(f); org.xml.sax.InputSource is = new org.xml.sax.InputSource(fis); Document d = parseXMLFile(is); fis.close(); fis = null; return d; } public Document parseXMLFile(File f) throws Exception { FileInputStream fis = new FileInputStream(f); org.xml.sax.InputSource is = new org.xml.sax.InputSource(fis); Document d = parseXMLFile(is); fis.close(); fis = null; return d; } private Document parseXMLFile(org.xml.sax.InputSource is) throws Exception { org.apache.xerces.parsers.DOMParser parser = new org.apache.xerces.parsers.DOMParser(); parser.parse(is); Document d = parser.getDocument(); parser.reset(); parser = null; return d; } public Element elementFromString(String s) throws Exception { ByteArrayInputStream bis = new ByteArrayInputStream(s.getBytes()); org.xml.sax.InputSource is = new org.xml.sax.InputSource(bis); Element e = parseXMLFile(is).getDocumentElement(); bis.close(); bis = null; return e; } public Hashtable<String, String> fillParameters(Hashtable<String, String> hash, NodeList list) { for (int i = 0; i < list.getLength(); i++) { if (list.item(i).getNodeType() == Node.ELEMENT_NODE) { if (list.item(i).getLocalName().equals("param")) { String name = ((Element) list.item(i)).getAttribute("name"); String val = ((Element) list.item(i)).getAttribute("value"); if (hash.get(name) != null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("WARNING those parameters have the same name :" + name); } } hash.put(name, val); } } } return hash; } // ========================================================================== // ============================= Instance Methods // =========================== // ========================================================================== public InspectorModel getInspectorModel(String inspectorName) { if (inspectorName == null) { return null; } InspectorModel answer = _inspectors.get(inspectorName); if (answer == null) { if (getInspectorNotFoundHandler() != null) { getInspectorNotFoundHandler().inspectorNotFound(inspectorName); answer = _inspectors.get(inspectorName); } } if (answer == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Sorry, I can't find inspector named : " + inspectorName); } } return answer; } public InspectorNotFoundHandler getInspectorNotFoundHandler() { return _inspectorNotFoundHandler; } public void setInspectorNotFoundHandler(InspectorNotFoundHandler notFoundHandler) { _inspectorNotFoundHandler = notFoundHandler; } /** * Adds an InspectorExceptionHandler * * @param exceptionHandler */ public void addInspectorExceptionHandler(InspectorExceptionHandler exceptionHandler) { _exceptionHandlers.add(exceptionHandler); } /** * Remove an InspectorExceptionHandler * * @param exceptionHandler */ public void removeInspectorExceptionHandler(InspectorExceptionHandler exceptionHandler) { _exceptionHandlers.remove(exceptionHandler); } /** * Tries to handle an exception raised during object inspection * * @param inspectable * the object on which exception was raised * @param propertyName * the concerned property name * @param value * the value that raised an exception * @param exception * the exception that was raised * @return a boolean indicating exception was correctely handled, or not */ @Override public boolean handleException(InspectableObject inspectable, String propertyName, Object value, Throwable exception) { for (Enumeration<InspectorExceptionHandler> en = _exceptionHandlers.elements(); en.hasMoreElements();) { InspectorExceptionHandler next = en.nextElement(); if (next.handleException(inspectable, propertyName, value, exception)) { return true; } } if (logger.isLoggable(Level.WARNING)) { logger.warning("Unexpected exception raised in Inspector. See console for details."); } exception.printStackTrace(); return false; } @Override public InspectorDelegate getDelegate() { return delegate; } @Override public HelpDelegate getHelpDelegate() { return helpDelegate; } @Override public void notifiedInspectedObjectChange(InspectableObject newInspectedObject) { // Dont care } // At this level, we only use inspector name as supplied in InspectableObject interface // But we may override this method to return a different value given a other context public String getInspectorName(InspectableObject object, Hashtable<String, Object> inspectionContext) { return object.getInspectorName(); } public String getWindowTitle(InspectorModelView currentTabPanel) { if (currentTabPanel != null) { if (currentTabPanel.getInspectedObject() != null && currentTabPanel.getInspectedObject().getInspectorTitle() != null) { return currentTabPanel.getInspectedObject().getInspectorTitle(); } return currentTabPanel.getName(); } else { return FlexoLocalization.localizedForKey("inspector"); } } public String getNothingToInspectLabel() { return FlexoLocalization.localizedForKey("nothing_to_inspect"); } public String getMultipleSelectionLabel() { return FlexoLocalization.localizedForKey("multiple_selection"); } public String getNonApplicableLabel() { return FlexoLocalization.localizedForKey("non_applicable"); } // Override when required @Override public boolean isTabPanelVisible(TabModel tab, InspectableObject inspectable) { if (tab.visibilityContext != null && getCurrentInspectionContext() != null) { // System.out.println("isTabPanelVisible() for tab "+tab.name+" visibilityContext="+tab.visibilityContext+" with "+getCurrentInspectionContext()); StringTokenizer st = new StringTokenizer(tab.visibilityContext, ","); while (st.hasMoreTokens()) { if (getCurrentInspectionContext().get(st.nextToken()) != null) { return true; } } return false; } return true; } @Override public final InspectorWidgetConfiguration getConfiguration() { /*if(inspectorConfiguration == null) inspectorConfiguration = new InspectorWidgetConfiguration() { public boolean showViewSourceButtonInWysiwyg() { return false; } };*/ return inspectorConfiguration; } }