//{HEADER
/**
* This class is part of jnex 'Nexirius Application Framework for Java'
*
* Copyright (C) Nexirius GmbH, CH-4450 Sissach, Switzerland (www.nexirius.ch)
*
* <p>This library is free software; you can redistribute it and/or<br>
* modify it under the terms of the GNU Lesser General Public<br>
* License as published by the Free Software Foundation; either<br>
* version 2.1 of the License, or (at your option) any later version.</p>
*
* <p>This library is distributed in the hope that it will be useful,<br>
* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU<br>
* Lesser General Public License for more details.</p>
*
* <p>You should have received a copy of the GNU Lesser General Public<br>
* License along with this library; if not, write to the Free Software<br>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p>
* </blockquote>
*
* <p>
* Nexirius GmbH, hereby disclaims all copyright interest in<br>
* the library jnex' 'Nexirius Application Framework for Java' written<br>
* by Marcel Baumann.</p>
*/
//}HEADER
package com.nexirius.framework.dataviewer;
import com.nexirius.framework.datamodel.DataModel;
import com.nexirius.framework.datamodel.DataModelEvent;
import com.nexirius.framework.datamodel.ModelFlag;
import com.nexirius.framework.datamodel.StructModel;
import com.nexirius.framework.gadgets.ArrayLayout;
import com.nexirius.framework.gadgets.ArrayPanel;
import com.nexirius.framework.swing.ClientResourceTitledBorder;
import com.nexirius.util.assertion.Assert;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EtchedBorder;
import java.awt.*;
/**
* This viewer is designed to show StructModel data in a JPanel. The default layout is
* a simple chain of structure member components which is diplayed in a single column.
* Each member is displayed together with a title frame which shows the field name of the
* member. There are three ways to avoid using default layout for structure information.
* Either you subclass this class and redefine the create method or you set the layout (setLayout)
* status of the struct viewer just after the factory has build it or you associate a layout
* status with the struct model.
* <PRE>
* ViewerFactory viewerFactory = new ViewerFactory(primaryProcessor);
*
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.AccountArrayModel", new AccountArrayLayout(), false);
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.MoneyModel", new MoneyEditorCreator());
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.AccountTableModel", new AccountTableLayout(), false);
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.SignatureCardModel", new SignatureCardLayout(), false);
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.AccountModel", new AccountDetailLayout(), false);
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.TransactionArrayModel", new TransactionArrayLayout(), false);
* viewerFactory.getViewerCreatorMap().registerTemplate("com.nexirius.client.caws.datamodel.TransactionModel", new TransactionModelLayout(), false);
* </PRE>
*
* @author Marcel Baumann
*/
public class StructViewer extends DataViewer {
public static final String s_viewername = "StructViewer";
public static final int MIN_WIDTH_VALUE = 200;
public static final int MIN_WIDTH_LABEL = 150;
/**
* Creates a new struct viewer
*/
public StructViewer(StructModel model) {
super(model);
}
/**
* Returns the factory which build this instance
*/
public ViewerFactory getFactory() {
return factory;
}
/**
* Returns the associated model
*/
public StructModel getModel() {
return (StructModel) getDataModel();
}
/**
* Returns the assotiated JPanel or null (if called before creation)
*/
public JPanel getJPanel() {
return (JPanel) getJComponent();
}
/**
* Creates the actual JPanel and all the children components (depends on the asssociated layout status)
*/
public void create() {
Assert.pre(this.factory != null, "Can't create a StructViewer with null factory (call setFactory())");
if (getLayout() == null) {
ArrayPanel arrayPanel = new ArrayPanel(false, ArrayLayout.FULL_SIZE);
setJComponent(arrayPanel);
Border border = arrayPanel.getBorder();
Border margin = new EtchedBorder();
arrayPanel.setBorder(new CompoundBorder(border, margin));
arrayPanel.setInnerMargin(5);
} else {
JPanel p = new JPanel(null);
p.setSize(100, 50);
setJComponent(p);
}
update();
}
public void dataModelChangeValue(DataModelEvent event) {
handleInvisibleFlag(event);
}
public void setVisible(boolean on) {
if (!isCreated()) {
return;
}
if (isVisible() != on) {
SwingUtilities.invokeLater(new SetVisible(on));
}
}
public boolean isVisible() {
if (!isCreated()) {
return false;
}
return getJComponent().isVisible();
}
class SetVisible implements Runnable {
boolean on;
SetVisible(boolean _on) {
on = _on;
}
public void run() {
getJComponent().setVisible(on);
}
}
/**
* Calls update
*
* @see #update
*/
public void dataModelChangeStructure(DataModelEvent event) {
if (!event.fromChild()) {
update();
}
if (isCreated()) {
getJPanel().repaint();
}
}
/**
* Add the given component to the associated JPanel
*/
public void add(JComponent component) {
Assert.pre(getJPanel() != null, "Can't add components to a StructViewer which is not created");
getJPanel().add(component);
}
/**
* Creates a tiltle border with the fieldname arround the specified data model component
*
* @param dm The child which gets the title frame
* @param panel The component which was created for the specified model
*/
public void createFieldName(DataModel dm, JComponent panel) {
ClientResourceTitledBorder tb = new ClientResourceTitledBorder(factory.getClientResource(), dm.getFieldName());
panel.setBorder(tb);
}
/**
* Creates a field viewer using the associated factory for the specified data model.
*
* @param dm any data modelk which shall be translated into a JComponent
*/
public JComponent createFieldValue(DataModel dm)
throws Exception {
JComponent ret = this.factory.createDefaultViewer(dm).getJComponent();
ret.setName(dm.getFieldName());
return ret;
}
/**
* Creates a field label
*
* @param dm any data modelk which shall be translated into a JComponent
*/
public JComponent createFieldLabel(DataModel dm)
throws Exception {
return getFactory().createJLabel(dm.getFieldName());
}
/**
* Removes all components of the current JPanel and recreates them. This method is
* automatically called whenever the associated data model structure fires a structure
* change event.
*/
public void update() {
if (isCreated()) {
getJPanel().removeAll();
if (getLayout() == null) {
for (DataModel dm = getModel().getChildren().firstItem(); dm != null; dm = getModel().getChildren().nextItem()) {
try {
JPanel panel = new JPanel(new BorderLayout());
JComponent comp = createFieldValue(dm);
if (comp != null) {
Dimension preferredSize = comp.getPreferredSize();
if (preferredSize.width < MIN_WIDTH_VALUE) {
preferredSize.width = MIN_WIDTH_VALUE;
comp.setPreferredSize(preferredSize);
}
panel.add(comp, BorderLayout.CENTER);
JComponent lab = createFieldLabel(dm);
preferredSize = lab.getPreferredSize();
if (preferredSize.width < MIN_WIDTH_LABEL) {
preferredSize.width = MIN_WIDTH_LABEL;
lab.setPreferredSize(preferredSize);
}
panel.add(lab, BorderLayout.WEST);
add(panel);
}
} catch (Exception ex) {
//FIX
ex.printStackTrace();
}
}
} else {
getLayout().doLayout(this);
}
updateUI();
}
}
/**
* Only used for debugging
*/
public String getViewerName() {
return s_viewername;
}
/**
* Not implemented for JPanel
*/
public void grabFocus() {
}
}