package es.icarto.gvsig.navtableforms.gui.tables; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import org.apache.log4j.Logger; import com.hardcode.gdbms.driver.exceptions.ReadDriverException; import com.iver.andami.PluginServices; import com.iver.andami.messages.NotificationManager; import com.iver.andami.ui.mdiFrame.MDIFrame; import com.iver.andami.ui.mdiManager.IWindow; import com.iver.andami.ui.mdiManager.IWindowListener; import com.iver.andami.ui.mdiManager.WindowInfo; import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException; import com.iver.cit.gvsig.fmap.edition.IEditableSource; import com.jeta.forms.components.image.ImageComponent; import com.jeta.forms.components.panel.FormPanel; import com.jeta.forms.gui.common.FormException; import com.toedter.calendar.JDateChooser; import es.icarto.gvsig.navtableforms.DependencyHandler; import es.icarto.gvsig.navtableforms.FillHandler; import es.icarto.gvsig.navtableforms.I18nHandler; import es.icarto.gvsig.navtableforms.II18nForm; import es.icarto.gvsig.navtableforms.IValidatableForm; import es.icarto.gvsig.navtableforms.ValidationHandler; import es.icarto.gvsig.navtableforms.calculation.Calculation; import es.icarto.gvsig.navtableforms.calculation.CalculationHandler; import es.icarto.gvsig.navtableforms.chained.ChainedHandler; import es.icarto.gvsig.navtableforms.gui.i18n.resource.I18nResource; import es.icarto.gvsig.navtableforms.gui.images.ImageHandler; import es.icarto.gvsig.navtableforms.gui.images.ImageHandlerManager; import es.icarto.gvsig.navtableforms.gui.tables.handler.BaseTableHandler; import es.icarto.gvsig.navtableforms.gui.tables.model.AlphanumericTableModel; import es.icarto.gvsig.navtableforms.ormlite.ORMLite; import es.icarto.gvsig.navtableforms.ormlite.domainvalidator.ValidatorForm; import es.icarto.gvsig.navtableforms.utils.AbeilleParser; import es.udc.cartolab.gvsig.navtable.dataacces.IController; import es.udc.cartolab.gvsig.navtable.dataacces.TableController; import es.udc.cartolab.gvsig.navtable.format.DateFormatNT; @SuppressWarnings("serial") public abstract class AbstractSubForm extends JPanel implements IForm, IValidatableForm, IWindow, IWindowListener, II18nForm { private static final Logger logger = Logger .getLogger(AbstractSubForm.class); private FormPanel formPanel; private HashMap<String, JComponent> widgets; private final I18nHandler i18nHandler; private final ValidationHandler validationHandler; private IController iController; private final ORMLite ormlite; private FillHandler fillHandler; private final DependencyHandler dependencyHandler; private final CalculationHandler calculationHandler; private final ChainedHandler chainedHandler; private ImageHandlerManager imageHandlerManager; private boolean isFillingValues; private boolean changedValues; private JPanel southPanel; protected JButton saveButton; private Map<String, String> foreingKey; private final List<BaseTableHandler> tableHandlers = new ArrayList<BaseTableHandler>(); private WindowInfo windowInfo; private final static int windowInfoCode = WindowInfo.MODELESSDIALOG | WindowInfo.PALETTE | WindowInfo.RESIZABLE; protected long position; protected ActionListener action; protected AlphanumericTableModel model; private String basicName; public AbstractSubForm(String basicName) { super(null); this.basicName = basicName; i18nHandler = new I18nHandler(this); initGUI(); ormlite = new ORMLite(getMetadataPath()); validationHandler = new ValidationHandler(ormlite, this); dependencyHandler = new DependencyHandler(ormlite, widgets, this); calculationHandler = new CalculationHandler(); chainedHandler = new ChainedHandler(); imageHandlerManager = new ImageHandlerManager(); } public AbstractSubForm() { super(); i18nHandler = new I18nHandler(this); initGUI(); ormlite = new ORMLite(getMetadataPath()); validationHandler = new ValidationHandler(ormlite, this); dependencyHandler = new DependencyHandler(ormlite, widgets, this); calculationHandler = new CalculationHandler(); chainedHandler = new ChainedHandler(); imageHandlerManager = new ImageHandlerManager(); } private void initGUI() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); getFormPanel(); JScrollPane scrollPane = new JScrollPane(formPanel); widgets = AbeilleParser.getWidgetsFromContainer(formPanel); for (JComponent c : getWidgets().values()) { if (c instanceof JDateChooser) { initDateChooser((JDateChooser) c); } } // AbeilleUtils au = new AbeilleUtils(); // au.formatLabels(formPanel); // au.formatTextArea(formPanel); add(scrollPane); add(getSouthPanel()); setFocusCycleRoot(true); i18nHandler.translateFormStaticTexts(); } private void initDateChooser(JDateChooser c) { SimpleDateFormat dateFormat = DateFormatNT.getDateFormat(); c.setDateFormatString(dateFormat.toPattern()); c.getDateEditor().setEnabled(false); c.getDateEditor().getUiComponent() .setBackground(new Color(255, 255, 255)); c.getDateEditor().getUiComponent() .setFont(new Font("Arial", Font.PLAIN, 11)); c.getDateEditor().getUiComponent().setToolTipText(null); } public void setForeingKey(Map<String, String> foreingKey) { this.foreingKey = foreingKey; } public Map<String, String> getForeignKey() { return foreingKey; } private JPanel getSouthPanel() { if (southPanel == null) { southPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); saveButton = new JButton("Guardar"); action = new CreateAction(this); saveButton.addActionListener(action); southPanel.add(saveButton); } return southPanel; } public void setListeners() { validationHandler.setListeners(widgets); dependencyHandler.setListeners(); for (BaseTableHandler tableHandler : tableHandlers) { tableHandler.reload(); } calculationHandler.setListeners(); chainedHandler.setListeners(); imageHandlerManager.setListeners(); } public void removeListeners() { validationHandler.removeListeners(widgets); dependencyHandler.removeListeners(); for (BaseTableHandler tableHandler : tableHandlers) { tableHandler.removeListeners(); } calculationHandler.removeListeners(); chainedHandler.removeListeners(); imageHandlerManager.removeListeners(); } public void fillEmptyValues() { setFillingValues(true); iController.clearAll(); ((TableController) iController).initMetadata(); fillHandler.fillEmptyWidgetsAndController(); for (String f : foreingKey.keySet()) { String value = foreingKey.get(f); JComponent widget = widgets.get(f); if (widget != null) { if (widget instanceof JTextField) { ((JTextField) widgets.get(f)).setText(value); } else if (widget instanceof JComboBox) { JComboBox combo = (JComboBox) widgets.get(f); for (int i = combo.getItemCount() - 1; i >= 0; i--) { if (combo.getItemAt(i).equals(value)) { combo.setSelectedIndex(i); } } } } iController.setValue(f, value); } fillSpecificValues(); dependencyHandler.fillValues(); chainedHandler.fillEmptyValues(); imageHandlerManager.fillEmptyValues(); // fillValues() setFillingValues(false); } protected void setFillingValues(boolean b) { isFillingValues = b; } protected void fillSpecificValues() { String key = getPrimaryKeyValue(); if (key != null) { for (BaseTableHandler tableHandler : tableHandlers) { tableHandler.fillValues(key); } } } protected String getPrimaryKeyValue() { return null; } /* * TODO call a method in a constructor (getBasicName) that can be override * for subclasses is no considered a good programming practice, in the * medium term this should be changed override for subclasses is no * considered a good programming practice, in the medium term this should be * changed */ protected String getBasicName() { return this.basicName; } public void fillValues() { setFillingValues(true); try { iController.read(position); fillHandler.fillValues(); dependencyHandler.fillValues(); fillSpecificValues(); } catch (ReadDriverException e) { logger.error(e.getStackTrace()); } chainedHandler.fillValues(); imageHandlerManager.fillValues(); setFillingValues(false); validationHandler.validate(); } public FormPanel getFormPanel() { if (formPanel == null) { InputStream stream = getClass().getClassLoader() .getResourceAsStream("/forms/" + getBasicName() + ".jfrm"); if (stream == null) { stream = getClass().getClassLoader().getResourceAsStream( "/forms/" + getBasicName() + ".xml"); } try { formPanel = new FormPanel(stream); } catch (FormException e) { e.printStackTrace(); } } return formPanel; } @Override public I18nResource[] getI18nResources() { return null; } @Override public I18nHandler getI18nHandler() { return i18nHandler; } protected String getMetadataPath() { return this.getClass().getClassLoader() .getResource("rules/" + getBasicName() + "_metadata.xml") .getPath(); } @Deprecated public HashMap<String, JComponent> getWidgetComponents() { return widgets; } @Override public Map<String, JComponent> getWidgets() { return widgets; } @Override public boolean isFillingValues() { return isFillingValues; } @Override public IController getFormController() { return iController; } @Override public void setChangedValues() { int[] indexes = iController.getIndexesOfValuesChanged(); if (indexes.length > 0) { setChangedValues(true); } else { setChangedValues(false); } } protected void enableSaveButton(boolean bool) { if (model != null && model.getSource().isEditing()) { saveButton.setEnabled(false); } else if (!isChangedValues()) { saveButton.setEnabled(false); } else if (validationHandler.hasValidationErrors()) { saveButton.setEnabled(false); } else { saveButton.setEnabled(bool); } } protected boolean isChangedValues() { return changedValues; } @Override public FillHandler getFillHandler() { return fillHandler; } @Override public void validateForm() { validationHandler.validate(); enableSaveButton(isChangedValues()); } @Override public ValidatorForm getValidatorForm() { return validationHandler.getValidatorForm(); } protected void setChangedValues(boolean bool) { changedValues = bool; } @Override public WindowInfo getWindowInfo() { if (windowInfo == null) { windowInfo = new WindowInfo(windowInfoCode); windowInfo.setTitle(PluginServices.getText(this, getBasicName())); Dimension dim = getPreferredSize(); // To calculate the maximum size of a form we take the size of the // main frame minus a "magic number" for the menus, toolbar, state // bar // Take into account that in edition mode there is less available // space MDIFrame a = (MDIFrame) PluginServices.getMainFrame(); int maxHeight = a.getHeight() - 205; int maxWidth = a.getWidth() - 15; int width, heigth = 0; if (dim.getHeight() > maxHeight) { heigth = maxHeight; } else { heigth = new Double(dim.getHeight()).intValue(); } if (dim.getWidth() > maxWidth) { width = maxWidth; } else { width = new Double(dim.getWidth()).intValue(); } // getPreferredSize doesn't take into account the borders and other // stuff // introduced by Andami, neither scroll bars so we must increase the // "preferred" // dimensions windowInfo.setWidth(width + 25); windowInfo.setHeight(heigth + 15); } return windowInfo; } @Override public Object getWindowProfile() { return WindowInfo.DIALOG_PROFILE; } @Override public void windowClosed() { removeListeners(); } @Override public void windowActivated() { } @Override public void actionCreateRecord() { this.position = -1; saveButton.removeActionListener(action); action = new CreateAction(this); saveButton.addActionListener(action); setListeners(); fillEmptyValues(); PluginServices.getMDIManager().addCentredWindow(this); } @Override public void actionUpdateRecord(long position) { this.position = position; saveButton.removeActionListener(action); action = new SaveAction(this); saveButton.addActionListener(action); setListeners(); fillValues(); PluginServices.getMDIManager().addCentredWindow(this); } @Override public void actionDeleteRecord(long position) { try { iController.delete((int) position); model.dataChanged(); } catch (Exception e) { NotificationManager.addError(e); } } @Override public IEditableSource getSource() { return model.getSource(); } @Override public void setModel(AlphanumericTableModel model) { this.model = model; iController = model.getController().clone(); fillHandler = new FillHandler(widgets, iController, ormlite.getAppDomain()); } protected void addTableHandler(BaseTableHandler tableHandler) { tableHandlers.add(tableHandler); } public List<BaseTableHandler> getTableHandlers() { return tableHandlers; } protected void addCalculation(Calculation calculation) { calculationHandler.add(calculation); } protected void addChained(JComponent chained, JComponent parent) { chainedHandler.add(this, chained, parent); } protected void addChained(String chained, String parent) { chainedHandler.add(this, widgets.get(chained), widgets.get(parent)); } protected void addChained(JComponent chained, JComponent... parents) { chainedHandler.add(this, chained, Arrays.asList(parents)); } protected void addChained(String chained, String... parents) { List<JComponent> parentList = new ArrayList<JComponent>(); for (String parent : parents) { parentList.add(widgets.get(parent)); } chainedHandler.add(this, widgets.get(chained), parentList); } /** * Instead of create an implementation of ImageHandler that only sets a path (FixedImageHandler) this utiliy method * sets the image without doing anything more * @param imgComponent * . Name of the abeille widget * @param absPath * . Absolute path to the image or relative path from andami.jar */ protected void addImageHandler(String imgComponent, String absPath) { ImageComponent image = (ImageComponent) formPanel .getComponentByName(imgComponent); ImageIcon icon = new ImageIcon(absPath); image.setIcon(icon); } protected void addImageHandler(ImageHandler imageHandler) { imageHandlerManager.addHandler(imageHandler); } private final class CreateAction implements ActionListener { private final IWindow iWindow; public CreateAction(IWindow iWindow) { this.iWindow = iWindow; } @Override public void actionPerformed(ActionEvent arg0) { HashMap<String, String> values = iController.getValues(); try { iController.create(values); model.dataChanged(); } catch (Exception e) { iController.clearAll(); position = -1; logger.error(e.getStackTrace(), e); } PluginServices.getMDIManager().closeWindow(iWindow); } } private final class SaveAction implements ActionListener { private final IWindow iWindow; public SaveAction(IWindow iWindow) { this.iWindow = iWindow; } @Override public void actionPerformed(ActionEvent arg0) { try { iController.update((int) position); model.dataChanged(); } catch (ReadDriverException e) { iController.clearAll(); position = -1; logger.error(e.getStackTrace()); } catch (StopWriterVisitorException e) { logger.error(e.getStackTrace()); String errorMessage = (e.getCause() != null) ? e.getCause() .getMessage() : e.getMessage(), auxMessage = errorMessage .replace("ERROR: ", "").replace(" ", "_") .replace("\n", ""), auxMessageIntl = PluginServices .getText(this, auxMessage); if (auxMessageIntl.compareToIgnoreCase(auxMessage) != 0) { errorMessage = auxMessageIntl; } JOptionPane.showMessageDialog( (Component) PluginServices.getMainFrame(), errorMessage, PluginServices.getText(this, "save_layer_error"), JOptionPane.ERROR_MESSAGE); } PluginServices.getMDIManager().closeWindow(iWindow); } } }