/* * (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.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.Enumeration; import java.util.Iterator; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.JPanel; import org.openflexo.inspector.model.GroupModel; import org.openflexo.inspector.model.InnerTabWidget; import org.openflexo.inspector.model.PropertyModel; import org.openflexo.inspector.model.TabModel; import org.openflexo.inspector.widget.CustomWidget; import org.openflexo.inspector.widget.DenaliWidget; import org.openflexo.inspector.widget.DenaliWidget.WidgetLayout; import org.openflexo.inspector.widget.InnerTabWidgetView; import org.openflexo.inspector.widget.LineWidget; import org.openflexo.localization.FlexoLocalization; /** * View representing a tab in th inspector * * @author bmangez,sguerin */ public class TabModelView extends JPanel { private static final Logger logger = Logger.getLogger(DenaliWidget.class.getPackage().getName()); // ========================================================================== // ============================= Variables ================================== // ========================================================================== private Vector<InnerTabWidgetView> _widgets; private Vector<InnerTabWidgetView> _visibleWidgets; private Vector<InnerTabWidgetView> _invisibleWidgets; private TabModel _tabModel; private InspectorModelView _inspectorModelView; private AbstractController _controller; // ========================================================================== // ============================= Constructor ================================ // ========================================================================== public TabModelView(TabModel model, InspectorModelView inspectorModelView, AbstractController controller) { super(); _controller = controller; _tabModel = model; _widgets = new Vector<InnerTabWidgetView>(); _visibleWidgets = new Vector<InnerTabWidgetView>(); _invisibleWidgets = new Vector<InnerTabWidgetView>(); _inspectorModelView = inspectorModelView; setName(FlexoLocalization.localizedForKey(model.name, this)); init(model, inspectorModelView); } public DenaliWidget getInspectorWidgetFor(String propertyName) { for (InnerTabWidgetView widget : _widgets) { if (widget instanceof DenaliWidget && ((DenaliWidget) widget).getPropertyModel().name.equals(propertyName)) { return (DenaliWidget) widget; } } return null; } /** * Overrides getPreferredSize * * @see javax.swing.JComponent#getPreferredSize() */ @Override public Dimension getPreferredSize() { if (_inspectorModelView == null || _inspectorModelView.getSelectedComponent() == this) { return super.getPreferredSize(); } else { return new Dimension(0, 0); } } private void init(TabModel model, InspectorModelView inspectorModelView) { GridBagLayout gridbag; gridbag = new GridBagLayout(); setLayout(gridbag); Iterator<InnerTabWidget> it = orderProperties(model).iterator(); int i = 0; while (it.hasNext()) { InnerTabWidget propModel = it.next(); InnerTabWidgetView widget = DenaliWidget.instance(propModel, _controller); widget.setTabModelView(this, i++); addField(gridbag, widget, widget.shouldExpandHorizontally(), widget.shouldExpandVertically()); _visibleWidgets.add(widget); ((Component) widget).setVisible(true); _widgets.add(widget); /*if (inspectorModelView != null) { inspectorModelView.addToWidgets(widget); }*/ if (logger.isLoggable(Level.FINE)) { logger.fine("Widget: " + widget.getXMLModel().getIndex() + " " + widget.getClass().getSimpleName() + ":" + widget.getName()); } } registerWidgets(); // Put a glue even if foundComponentAllowingVerticalExpansion is true, // in case of component allowing expansion is hidden because of a "depends" // if (!foundComponentAllowingVerticalExpansion) { GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 0.1; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.CENTER; Component glue = Box.createGlue(); gridbag.setConstraints(glue, c); add(glue); // } validate(); } private boolean _widgetsAreRegisteredInInspectorModelView = false; protected void registerWidgets() { if (!_widgetsAreRegisteredInInspectorModelView && _inspectorModelView != null) { for (InnerTabWidgetView widget : _widgets) { _inspectorModelView.addToWidgets(widget); } _widgetsAreRegisteredInInspectorModelView = true; // System.out.println("Registered widgets in TabModelView"); } } protected void unregisterWidgets() { if (_widgetsAreRegisteredInInspectorModelView && _inspectorModelView != null) { for (InnerTabWidgetView widget : _widgets) { _inspectorModelView.removeFromWidgets(widget); } _widgetsAreRegisteredInInspectorModelView = false; // System.out.println("Un-registered widgets in TabModelView"); } } private void addField(GridBagLayout gridbag, InnerTabWidgetView widget, boolean expandX, boolean expandY) { GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(3, 3, 3, 3); if (widget.displayLabel()) { if (widget.getWidgetLayout() == WidgetLayout.LABEL_NEXTTO_WIDGET_LAYOUT) { c.fill = GridBagConstraints.NONE; c.weightx = 0; // 1.0; c.gridwidth = GridBagConstraints.RELATIVE; c.anchor = GridBagConstraints.NORTHEAST; } else if (widget.getWidgetLayout() == WidgetLayout.LABEL_ABOVE_WIDGET_LAYOUT) { c.fill = GridBagConstraints.NONE; c.weightx = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.CENTER; } gridbag.setConstraints(widget.getLabel(), c); add(widget.getLabel()); } if (expandX) { c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; if (expandY) { c.weighty = 1.0; // c.gridheight = GridBagConstraints.RELATIVE; } } else { c.fill = GridBagConstraints.NONE; if (!widget.displayLabel()) { // GPO: if there are no label and the widget does not expand horizontally, then we center it on its line c.anchor = GridBagConstraints.CENTER; } else { c.anchor = GridBagConstraints.WEST; } } c.weightx = 1.0; // 2.0; c.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(widget.getDynamicComponent(), c); add(widget.getDynamicComponent()); } // OLD IMPLEMENTATION WITH VERTICAL LAYOUT /*private void init(TabModel model, InspectorModelView inspectorModelView) { Iterator it = model.getProperties().values().iterator(); biggestLabelLength = (biggestLabelLength + 3) * 8; setLayout(new VerticalLayout(1, 1, 1)); it = orderProperties(model.getProperties().values().iterator()).iterator(); int i = 0; while (it.hasNext()) { PropertyModel propModel = (PropertyModel) it.next(); DenaliWidget widget = DenaliWidget.instance(propModel,_controller); widget.setTabModelView(this,i++); FontMetrics fm = widget.getLabel().getFontMetrics(widget.getLabel().getFont()); biggestLabelLength = Math.max(biggestLabelLength, fm.stringWidth(widget.getLabel().getText())); add(widgetPanel(widget)); _visibleWidgets.add(widget); _widgets.add(widget); if (inspectorModelView != null) { inspectorModelView.addToWidgets(widget); } } for (Enumeration e = _visibleWidgets.elements(); e.hasMoreElements();) { DenaliWidget widget = (DenaliWidget) e.nextElement(); widget.getLabel().setPreferredSize(new Dimension(biggestLabelLength, 24)); } validate(); }*/ /*public static JPanel widgetPanel(DenaliWidget widget) { if (widget.getWidgetLayout()==DenaliWidget.LABEL_ABOVE_WIDGET_LAYOUT){ if (widget instanceof PropertyListWidget) { return new PropertyListWidgetPanel((PropertyListWidget) widget); } else return new SpanWidgetPanel(widget); } else { return new WidgetPanel(widget); } }*/ private Vector<InnerTabWidget> orderProperties(TabModel model) { Vector<InnerTabWidget> answer = new Vector<InnerTabWidget>(); Iterator<PropertyModel> it = model.getProperties().values().iterator(); while (it.hasNext()) { PropertyModel propModel = it.next(); if (answer.size() == 0) { answer.add(propModel); } else { Enumeration en = answer.elements(); boolean notInserted = true; int propIndex = propModel.getIndex(); while (en.hasMoreElements() && notInserted) { PropertyModel curProp = (PropertyModel) en.nextElement(); if (curProp.getIndex() > propIndex) { answer.add(answer.indexOf(curProp), propModel); notInserted = false; } } if (notInserted) { answer.add(propModel); } } } Iterator<GroupModel> i = model.getGroups().values().iterator(); while (i.hasNext()) { GroupModel lineModel = i.next(); if (answer.size() == 0) { answer.add(lineModel); } else { Enumeration<InnerTabWidget> en = answer.elements(); boolean notInserted = true; int lineIndex = lineModel.getIndex(); while (en.hasMoreElements() && notInserted) { InnerTabWidget curProp = en.nextElement(); if (curProp.getIndex() > lineIndex) { answer.add(answer.indexOf(curProp), lineModel); notInserted = false; } } if (notInserted) { answer.add(lineModel); } } } return answer; } // public int biggestLabelLength = 0; public AbstractController getController() { return _controller; } /** * @param newValue * @param widget */ public void valueChange(InspectableObject object) { if (logger.isLoggable(Level.FINE)) { logger.fine("valueChange() in TabModelView for inspectable " + object); } Enumeration<InnerTabWidgetView> en = _visibleWidgets.elements(); DenaliWidget cur = null; Vector<DenaliWidget> widgetsToHide = new Vector<DenaliWidget>(); Vector<DenaliWidget> widgetsToShow = new Vector<DenaliWidget>(); while (en.hasMoreElements()) { InnerTabWidgetView inner = en.nextElement(); if (inner instanceof DenaliWidget) { cur = (DenaliWidget) inner; } else if (inner instanceof LineWidget) { ((LineWidget) inner).valueChange(object); continue; } else { if (logger.isLoggable(Level.SEVERE)) { logger.severe("Unknown class " + inner.getClass().getSimpleName()); } continue; } boolean isStillVisible = cur.isVisible(object); if (!isStillVisible) { widgetsToHide.add(cur); } // logger.info ("WAS visible: "+cur.getObservedPropertyName()+" still visible "+isStillVisible); } en = _invisibleWidgets.elements(); while (en.hasMoreElements()) { InnerTabWidgetView inner = en.nextElement(); if (inner instanceof DenaliWidget) { cur = (DenaliWidget) inner; } else { continue; } boolean isStillInvisible = !cur.isVisible(object); if (!isStillInvisible) { widgetsToShow.add(cur); } // logger.info ("WAS invisible: "+cur.getObservedPropertyName()+" still invisible "+isStillInvisible); } if (widgetsToHide.size() > 0) { processToHiding(widgetsToHide); } if (widgetsToShow.size() > 0) { processToShowing(widgetsToShow); } validate(); repaint(); } /** * @param newValue * @param widget */ public void valueChange(Object newValue, DenaliWidget widget) { // System.out.println ("valueChange() with "+newValue+" for "+widget.getObservedPropertyName()); if (logger.isLoggable(Level.FINE)) { logger.fine("valueChange() in TabModelView for property " + widget.getObservedPropertyName() + " which receive " + newValue); } Enumeration<InnerTabWidgetView> en = _visibleWidgets.elements(); DenaliWidget cur = null; Vector<DenaliWidget> widgetsToHide = new Vector<DenaliWidget>(); Vector<DenaliWidget> widgetsToShow = new Vector<DenaliWidget>(); while (en.hasMoreElements()) { InnerTabWidgetView inner = en.nextElement(); if (inner instanceof DenaliWidget) { cur = (DenaliWidget) inner; } else if (inner instanceof LineWidget) { ((LineWidget) inner).valueChange(newValue, widget); continue; } else { if (logger.isLoggable(Level.SEVERE)) { logger.severe("Unknown class " + inner.getClass().getSimpleName()); } continue; } boolean isStillVisible = cur.isStillVisible(newValue, widget.getObservedPropertyName()); if (!isStillVisible) { widgetsToHide.add(cur); } // System.out.println (""+cur.getObservedPropertyName()+": dependsOfProperty(widget)="+cur.dependsOfProperty(widget)); if (cur.dependsOfProperty(widget)) { if (cur.isWidgetVisible()) { cur.updateWidgetFromModel(); } if (cur instanceof CustomWidget) { ((CustomWidget) cur).performModelUpdating(); } } // logger.info ("WAS visible: "+cur.getObservedPropertyName()+" still visible "+isStillVisible); } en = _invisibleWidgets.elements(); while (en.hasMoreElements()) { InnerTabWidgetView inner = en.nextElement(); if (inner instanceof DenaliWidget) { cur = (DenaliWidget) inner; } else { continue; } boolean isStillInvisible = cur.isStillInvisible(newValue, widget.getObservedPropertyName()); if (!isStillInvisible) { widgetsToShow.add(cur); } // logger.info ("WAS invisible: "+cur.getObservedPropertyName()+" still invisible "+isStillInvisible); } if (widgetsToHide.size() > 0) { processToHiding(widgetsToHide); } if (widgetsToShow.size() > 0) { processToShowing(widgetsToShow); } // AJA : changed updateUI to revalidate repaint; revalidate(); repaint(); } private void processToHiding(Vector<DenaliWidget> widgetsToHide) { if (logger.isLoggable(Level.FINE)) { logger.fine("processToHiding() for " + _tabModel.name); } DenaliWidget cur = null; Enumeration<DenaliWidget> en = widgetsToHide.elements(); while (en.hasMoreElements()) { cur = en.nextElement(); if (logger.isLoggable(Level.FINE)) { logger.fine("try to hide " + cur.getObservedPropertyName() + " at index: " + cur.getIndexInTab()); } for (int i = 0; i < getComponentCount(); i++) { if (getComponent(i) == cur.getDynamicComponent()) { if (cur.getLabel() != null) { cur.getLabel().setVisible(false); } getComponent(i).setVisible(false); _visibleWidgets.remove(cur); _invisibleWidgets.add(cur); if (logger.isLoggable(Level.FINE)) { logger.fine("HIDE: " + cur.getObservedPropertyName()); } } } } } private void processToShowing(Vector<DenaliWidget> widgetsToShow) { if (logger.isLoggable(Level.FINE)) { logger.fine("processToShowing() for " + _tabModel.name); } DenaliWidget cur = null; Enumeration<DenaliWidget> en = widgetsToShow.elements(); while (en.hasMoreElements()) { cur = en.nextElement(); cur.performUpdate(); if (logger.isLoggable(Level.FINE)) { logger.fine("try to show " + cur.getObservedPropertyName() + " at index: " + cur.getIndexInTab()); } cur.setTabModelView(this); cur.getDynamicComponent().setVisible(true); if (cur.getLabel() != null) { cur.getLabel().setVisible(true); } _visibleWidgets.add(cur); _invisibleWidgets.remove(cur); if (logger.isLoggable(Level.FINE)) { logger.fine("SHOW: " + cur.getObservedPropertyName()); } } } /** * Must be called outside the context of full-inspector * * @param newInspectable */ public void performObserverSwitch(InspectableObject newInspectable) { Enumeration<InnerTabWidgetView> en = _widgets.elements(); while (en.hasMoreElements()) { en.nextElement().switchObserved(newInspectable); } } public InspectorModelView getInspectorModelView() { return _inspectorModelView; } public TabModel getTabModel() { return _tabModel; } public boolean hasVisibleWidgets() { return _visibleWidgets.size() > 0; } protected Enumeration<InnerTabWidgetView> getAllWidgets() { return _widgets.elements(); } public void requestFocusInFirstWidget() { if (_widgets.size() > 0) { _widgets.firstElement().getDynamicComponent().requestFocusInWindow(); // System.out.println("Request focus for "+_widgets.firstElement().getDynamicComponent()); } } public void requestFocusInSecondWidget() { if (_widgets.size() > 1) { _widgets.elementAt(1).getDynamicComponent().requestFocusInWindow(); // System.out.println("Request focus for "+_widgets.elementAt(1).getDynamicComponent()); } } }