/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jspresso 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.view.swing; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TimeZone; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultListCellRenderer; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JPopupMenu; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.JToolBar; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import javax.swing.text.DateFormatter; import javax.swing.text.DefaultFormatterFactory; import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLEditorKit; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import chrriis.dj.swingsuite.JComboButton; import chrriis.dj.swingsuite.JLink; import chrriis.dj.swingsuite.JTriStateCheckBox; import chrriis.dj.swingsuite.LinkListener; import com.bbn.openmap.LayerHandler; import com.bbn.openmap.MapBean; import com.bbn.openmap.MapHandler; import com.bbn.openmap.MouseDelegator; import com.bbn.openmap.event.OMMouseMode; import com.bbn.openmap.gui.BasicMapPanel; import com.bbn.openmap.gui.EmbeddedNavPanel; import com.bbn.openmap.gui.EmbeddedScaleDisplayPanel; import com.bbn.openmap.gui.OverlayMapPanel; import com.bbn.openmap.layer.imageTile.MapTileLayer; import org.syntax.jedit.JEditTextArea; import org.syntax.jedit.tokenmarker.TokenMarker; import org.jspresso.framework.action.ActionContextConstants; import org.jspresso.framework.action.IAction; import org.jspresso.framework.action.IActionHandler; import org.jspresso.framework.application.view.ControllerAwareViewFactory; import org.jspresso.framework.binding.AbstractCompositeValueConnector; import org.jspresso.framework.binding.ICollectionConnector; import org.jspresso.framework.binding.ICollectionConnectorProvider; import org.jspresso.framework.binding.ICompositeValueConnector; import org.jspresso.framework.binding.IRenderableCompositeValueConnector; import org.jspresso.framework.binding.IValueConnector; import org.jspresso.framework.binding.basic.BasicValueConnector; import org.jspresso.framework.binding.model.ModelRefPropertyConnector; import org.jspresso.framework.binding.swing.CollectionConnectorListModel; import org.jspresso.framework.binding.swing.CollectionConnectorTableModel; import org.jspresso.framework.binding.swing.ConnectorHierarchyTreeModel; import org.jspresso.framework.binding.swing.IListSelectionModelBinder; import org.jspresso.framework.binding.swing.ITreeSelectionModelBinder; import org.jspresso.framework.binding.swing.JActionFieldConnector; import org.jspresso.framework.binding.swing.JColorPickerConnector; import org.jspresso.framework.binding.swing.JComboBoxConnector; import org.jspresso.framework.binding.swing.JDateFieldConnector; import org.jspresso.framework.binding.swing.JEditTextAreaConnector; import org.jspresso.framework.binding.swing.JFormattedFieldConnector; import org.jspresso.framework.binding.swing.JHTMLEditorConnector; import org.jspresso.framework.binding.swing.JImageConnector; import org.jspresso.framework.binding.swing.JLabelConnector; import org.jspresso.framework.binding.swing.JMapViewConnector; import org.jspresso.framework.binding.swing.JPasswordFieldConnector; import org.jspresso.framework.binding.swing.JPercentFieldConnector; import org.jspresso.framework.binding.swing.JRadioButtonConnector; import org.jspresso.framework.binding.swing.JReferenceFieldConnector; import org.jspresso.framework.binding.swing.JTextAreaConnector; import org.jspresso.framework.binding.swing.JTextFieldConnector; import org.jspresso.framework.binding.swing.JTextPaneConnector; import org.jspresso.framework.binding.swing.JToggleButtonConnector; import org.jspresso.framework.binding.swing.JTriStateCheckBoxConnector; import org.jspresso.framework.gui.swing.components.JActionField; import org.jspresso.framework.gui.swing.components.JColorPicker; import org.jspresso.framework.gui.swing.components.JDateField; import org.jspresso.framework.gui.swing.components.JHTMLEditor; import org.jspresso.framework.gui.swing.components.JScrollablePanel; import org.jspresso.framework.model.descriptor.IBinaryPropertyDescriptor; import org.jspresso.framework.model.descriptor.IBooleanPropertyDescriptor; import org.jspresso.framework.model.descriptor.ICollectionDescriptorProvider; import org.jspresso.framework.model.descriptor.ICollectionPropertyDescriptor; import org.jspresso.framework.model.descriptor.IColorPropertyDescriptor; import org.jspresso.framework.model.descriptor.IComponentDescriptor; import org.jspresso.framework.model.descriptor.IComponentDescriptorProvider; import org.jspresso.framework.model.descriptor.IDatePropertyDescriptor; import org.jspresso.framework.model.descriptor.IDecimalPropertyDescriptor; import org.jspresso.framework.model.descriptor.IDurationPropertyDescriptor; import org.jspresso.framework.model.descriptor.IEnumerationPropertyDescriptor; import org.jspresso.framework.model.descriptor.IHtmlPropertyDescriptor; import org.jspresso.framework.model.descriptor.IImageBinaryPropertyDescriptor; import org.jspresso.framework.model.descriptor.IImageUrlPropertyDescriptor; import org.jspresso.framework.model.descriptor.IIntegerPropertyDescriptor; import org.jspresso.framework.model.descriptor.IModelDescriptor; import org.jspresso.framework.model.descriptor.INumberPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPasswordPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPercentPropertyDescriptor; import org.jspresso.framework.model.descriptor.IPropertyDescriptor; import org.jspresso.framework.model.descriptor.IReferencePropertyDescriptor; import org.jspresso.framework.model.descriptor.IRelationshipEndPropertyDescriptor; import org.jspresso.framework.model.descriptor.ISourceCodePropertyDescriptor; import org.jspresso.framework.model.descriptor.IStringPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITextPropertyDescriptor; import org.jspresso.framework.model.descriptor.ITimePropertyDescriptor; import org.jspresso.framework.util.event.IValueChangeListener; import org.jspresso.framework.util.event.ValueChangeEvent; import org.jspresso.framework.util.format.IFormatter; import org.jspresso.framework.util.format.PasswordFormatter; import org.jspresso.framework.util.gui.CellConstraints; import org.jspresso.framework.util.gui.ColorHelper; import org.jspresso.framework.util.gui.ERenderingOptions; import org.jspresso.framework.util.gui.FontHelper; import org.jspresso.framework.util.i18n.ITranslationProvider; import org.jspresso.framework.util.image.IScalableImageAware; import org.jspresso.framework.util.swing.SwingUtil; import org.jspresso.framework.util.url.UrlHelper; import org.jspresso.framework.view.BasicCompositeView; import org.jspresso.framework.view.BasicIndexedView; import org.jspresso.framework.view.BasicMapView; import org.jspresso.framework.view.BasicView; import org.jspresso.framework.view.IActionFactory; import org.jspresso.framework.view.ICompositeView; import org.jspresso.framework.view.IMapView; import org.jspresso.framework.view.IView; import org.jspresso.framework.view.ViewException; import org.jspresso.framework.view.action.ActionList; import org.jspresso.framework.view.action.ActionMap; import org.jspresso.framework.view.action.IDisplayableAction; import org.jspresso.framework.view.descriptor.EHorizontalAlignment; import org.jspresso.framework.view.descriptor.EHorizontalPosition; import org.jspresso.framework.view.descriptor.ELabelPosition; import org.jspresso.framework.view.descriptor.IActionViewDescriptor; import org.jspresso.framework.view.descriptor.IBorderViewDescriptor; import org.jspresso.framework.view.descriptor.ICardViewDescriptor; import org.jspresso.framework.view.descriptor.ICollectionViewDescriptor; import org.jspresso.framework.view.descriptor.IComponentViewDescriptor; import org.jspresso.framework.view.descriptor.IConstrainedGridViewDescriptor; import org.jspresso.framework.view.descriptor.IEnumerationPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IEvenGridViewDescriptor; import org.jspresso.framework.view.descriptor.IImageViewDescriptor; import org.jspresso.framework.view.descriptor.IListViewDescriptor; import org.jspresso.framework.view.descriptor.IMapViewDescriptor; import org.jspresso.framework.view.descriptor.IPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IReferencePropertyViewDescriptor; import org.jspresso.framework.view.descriptor.IRepeaterViewDescriptor; import org.jspresso.framework.view.descriptor.IScrollableViewDescriptor; import org.jspresso.framework.view.descriptor.ISplitViewDescriptor; import org.jspresso.framework.view.descriptor.IStaticTextViewDescriptor; import org.jspresso.framework.view.descriptor.IStringPropertyViewDescriptor; import org.jspresso.framework.view.descriptor.ITabViewDescriptor; import org.jspresso.framework.view.descriptor.ITableViewDescriptor; import org.jspresso.framework.view.descriptor.ITreeViewDescriptor; import org.jspresso.framework.view.descriptor.IViewDescriptor; import org.jspresso.framework.view.descriptor.TreeDescriptorHelper; /** * Factory for swing views. * * @author Vincent Vandenschrick */ @SuppressWarnings("UnusedParameters") public class DefaultSwingViewFactory extends ControllerAwareViewFactory<JComponent, Icon, Action> { private static final Dimension TREE_PREFERRED_SIZE = new Dimension(128, 128); private IListSelectionModelBinder listSelectionModelBinder; private ITreeSelectionModelBinder treeSelectionModelBinder; /** * {@inheritDoc} */ @Override protected JComponent applyComponentScrollability(JComponent viewComponent, IScrollableViewDescriptor viewDescriptor) { JScrollPane scrollPane = createJScrollPane(); scrollPane.setBorder(BorderFactory.createEmptyBorder()); scrollPane.setVerticalScrollBarPolicy( viewDescriptor.isVerticallyScrollable() ? ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED : ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); scrollPane.setHorizontalScrollBarPolicy( viewDescriptor.isHorizontallyScrollable() ? ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED : ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); if (viewComponent instanceof JScrollablePanel) { ((JScrollablePanel) viewComponent).setScrollableTracksViewportHeight(!viewDescriptor.isVerticallyScrollable()); ((JScrollablePanel) viewComponent).setScrollableTracksViewportWidth(!viewDescriptor.isHorizontallyScrollable()); } scrollPane.setViewportView(viewComponent); return scrollPane; } /** * Sets the listSelectionModelBinder. * * @param listSelectionModelBinder * the listSelectionModelBinder to set. */ public void setListSelectionModelBinder(IListSelectionModelBinder listSelectionModelBinder) { this.listSelectionModelBinder = listSelectionModelBinder; } /** * Sets the treeSelectionModelBinder. * * @param treeSelectionModelBinder * the treeSelectionModelBinder to set. */ public void setTreeSelectionModelBinder(ITreeSelectionModelBinder treeSelectionModelBinder) { this.treeSelectionModelBinder = treeSelectionModelBinder; } /** * {@inheritDoc} */ @Override protected void addCard(IMapView<JComponent> cardView, IView<JComponent> card, String cardName) { Container cardPanel = findFirstCardPanel(cardView.getPeer()); if (cardPanel != null) { cardPanel.add(card.getPeer(), cardName); cardView.addToChildrenMap(cardName, card); } } /** * Finds the first card panel starting from a root component. * * @param root * the root component to start for searching. * @return the 1st found card panel or null if none. */ protected JComponent findFirstCardPanel(Component root) { if (root instanceof JComponent && ((JComponent) root).getLayout() instanceof CardLayout) { return (JComponent) root; } if (root instanceof Container) { for (Component child : ((Container) root).getComponents()) { JComponent childCardPanel = findFirstCardPanel(child); if (childCardPanel != null) { return childCardPanel; } } } return null; } /** * Adjusts a component various sizes (e.g. min, max, preferred) based on a * formatter and a template value. * * @param component * the component to adjust the sizes for. * @param formatter * the formatter used if any. * @param templateValue * the template value used. * @param viewDescriptor * the underlying view descriptor. */ protected void adjustSizes(IViewDescriptor viewDescriptor, JComponent component, IFormatter<?, String> formatter, Object templateValue) { adjustSizes(viewDescriptor, component, formatter, templateValue, 32); } /** * Adjusts a component various sizes (e.g. min, max, preferred) based on a * formatter and a template value. * * @param component * the component to adjust the sizes for. * @param formatter * the formatter used if any. * @param templateValue * the template value used. * @param viewDescriptor * the underlying view descriptor. * @param extraWidth * the extra size to be added. */ protected void adjustSizes(IViewDescriptor viewDescriptor, JComponent component, IFormatter<?, String> formatter, Object templateValue, int extraWidth) { if (viewDescriptor.getFont() != null && FontHelper.isFontSpec(viewDescriptor.getFont())) { // must set font before computing size. component.setFont(createFont(viewDescriptor.getFont(), component.getFont())); } int preferredWidth = computePixelWidth(component, getFormatLength(formatter, templateValue)) + extraWidth; Dimension size = new Dimension(preferredWidth, component.getPreferredSize().height); component.setMinimumSize(size); component.setPreferredSize(size); component.setMaximumSize(size); } /** * {@inheritDoc} */ @Override protected void applyPreferredSize(JComponent component, org.jspresso.framework.util.gui.Dimension preferredSize) { if (preferredSize != null) { int pW = preferredSize.getWidth(); if (pW <= 0) { pW = component.getPreferredSize().width; } int pH = preferredSize.getHeight(); if (pH <= 0) { pH = component.getPreferredSize().height; } component.setPreferredSize(new Dimension(pW, pH)); } } private int computePixelWidth(JComponent component, int characterLength) { int charLength = getMaxCharacterLength() + 2; if (characterLength > 0 && characterLength < getMaxCharacterLength()) { charLength = characterLength + 2; } return component.getFont().getSize() * charLength / 2; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createActionView(IActionViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JPanel viewComponent = createJPanel(); IValueConnector connector = getConnectorFactory().createValueConnector(ModelRefPropertyConnector.THIS_PROPERTY); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, viewDescriptor, connector); ActionList actionList = viewDescriptor.getActionList(); if (viewDescriptor.getActionList() != null) { ERenderingOptions defaultRenderingOptions = ERenderingOptions.ICON; if (viewDescriptor.getRenderingOptions() != null) { defaultRenderingOptions = viewDescriptor.getRenderingOptions(); } boolean defaultHideActionWhenDisabled = getDefaultHideActionWhenDisabled(); if (viewDescriptor.getActionList().getHideActionWhenDisabled() != null) { defaultHideActionWhenDisabled = viewDescriptor.getActionList().getHideActionWhenDisabled(); } List<JButton> viewActionList = createViewActionList(viewDescriptor.getActionList(), defaultRenderingOptions, defaultHideActionWhenDisabled, view, actionHandler, locale); if (viewActionList != null) { FlowLayout layout = new FlowLayout(); viewComponent.setLayout(layout); JToolBar toolBar = createJToolBar(); for (JButton toolbarButton : viewActionList) { toolBar.add(toolbarButton); } viewComponent.add(toolBar); } } else { BorderLayout layout = new BorderLayout(); viewComponent.setLayout(layout); JButton actionButton = createJButton(); actionButton.setAction(getActionFactory() .createAction(viewDescriptor.getAction(), viewDescriptor.getPreferredSize(), actionHandler, view, locale)); actionButton.setBorderPainted(false); switch (viewDescriptor.getRenderingOptions()) { case ICON: actionButton.setText(null); break; case LABEL: actionButton.setIcon(null); break; default: break; } viewComponent.add(actionButton, BorderLayout.CENTER); } return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createBinaryPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IBinaryPropertyDescriptor propertyDescriptor = (IBinaryPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JActionField viewComponent = createJActionField(propertyViewDescriptor, false); JActionFieldConnector connector = new JActionFieldConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); IView<JComponent> propertyView = constructView(viewComponent, propertyViewDescriptor, connector); viewComponent.setActions(createBinaryActions(propertyView, actionHandler, locale)); adjustSizes(propertyViewDescriptor, viewComponent, null, null); return propertyView; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createBooleanPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IBooleanPropertyDescriptor propertyDescriptor = (IBooleanPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JComponent viewComponent; IValueConnector connector; if (propertyDescriptor.isMandatory()) { viewComponent = createJCheckBox(propertyViewDescriptor); connector = new JToggleButtonConnector<>(propertyDescriptor.getName(), (JCheckBox) viewComponent); } else { viewComponent = createJTriStateCheckBox(propertyViewDescriptor); connector = new JTriStateCheckBoxConnector(propertyDescriptor.getName(), (JTriStateCheckBox) viewComponent); } connector.setExceptionHandler(actionHandler); return constructView(viewComponent, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @Override protected ICompositeView<JComponent> createBorderView(IBorderViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JPanel viewComponent = createJPanel(); BasicCompositeView<JComponent> view = constructCompositeView(viewComponent, viewDescriptor); List<IView<JComponent>> childrenViews = new ArrayList<>(); BorderLayout layout = new BorderLayout(); viewComponent.setLayout(layout); if (viewDescriptor.getNorthViewDescriptor() != null) { IView<JComponent> northView = createView(viewDescriptor.getNorthViewDescriptor(), actionHandler, locale); viewComponent.add(northView.getPeer(), BorderLayout.NORTH); childrenViews.add(northView); } if (viewDescriptor.getWestViewDescriptor() != null) { IView<JComponent> westView = createView(viewDescriptor.getWestViewDescriptor(), actionHandler, locale); viewComponent.add(westView.getPeer(), BorderLayout.WEST); childrenViews.add(westView); } if (viewDescriptor.getCenterViewDescriptor() != null) { IView<JComponent> centerView = createView(viewDescriptor.getCenterViewDescriptor(), actionHandler, locale); viewComponent.add(centerView.getPeer(), BorderLayout.CENTER); childrenViews.add(centerView); } if (viewDescriptor.getEastViewDescriptor() != null) { IView<JComponent> eastView = createView(viewDescriptor.getEastViewDescriptor(), actionHandler, locale); viewComponent.add(eastView.getPeer(), BorderLayout.EAST); childrenViews.add(eastView); } if (viewDescriptor.getSouthViewDescriptor() != null) { IView<JComponent> southView = createView(viewDescriptor.getSouthViewDescriptor(), actionHandler, locale); viewComponent.add(southView.getPeer(), BorderLayout.SOUTH); childrenViews.add(southView); } view.setChildren(childrenViews); return view; } /** * {@inheritDoc} */ @Override protected IMapView<JComponent> createCardView(ICardViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JPanel viewComponent = createJPanel(); CardLayout layout = new CardLayout(); viewComponent.setLayout(layout); BasicMapView<JComponent> view = constructMapView(viewComponent, viewDescriptor); viewComponent.add(createEmptyComponent(), ICardViewDescriptor.DEFAULT_CARD); viewComponent.add(createSecurityComponent(), ICardViewDescriptor.SECURITY_CARD); view.setConnector(createCardViewConnector(view, actionHandler, locale)); return view; } private void fillLastRow(JPanel viewComponent) { GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = GridBagConstraints.RELATIVE; constraints.weightx = 2000.0; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridwidth = GridBagConstraints.REMAINDER; JPanel filler = createJPanel(); // filler.setBorder(new LineBorder(Color.BLUE)); viewComponent.add(filler, constraints); } /** * {@inheritDoc} */ @Override protected IView<JComponent> createColorPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IColorPropertyDescriptor propertyDescriptor = (IColorPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JColorPicker viewComponent = createJColorPicker(propertyViewDescriptor); if (propertyDescriptor.getDefaultValue() != null) { int[] rgba = ColorHelper.fromHexString((String) propertyDescriptor.getDefaultValue()); viewComponent.setResetValue(new Color(rgba[0], rgba[1], rgba[2], rgba[3])); } else { if (propertyDescriptor.isMandatory()) { viewComponent.setResetEnabled(false); } } JColorPickerConnector connector = new JColorPickerConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); return constructView(viewComponent, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @SuppressWarnings({"unchecked", "ConstantConditions"}) @Override protected IView<JComponent> createComponentView(IComponentViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { final JPanel viewComponent = createJPanel(); IComponentDescriptor<?> modelDescriptor = ((IComponentDescriptorProvider<?>) viewDescriptor.getModelDescriptor()) .getComponentDescriptor(); String toolTipProperty = computeComponentDynamicToolTip(viewDescriptor, modelDescriptor); IRenderableCompositeValueConnector connector = getConnectorFactory().createCompositeValueConnector( getConnectorIdForBeanView(viewDescriptor), toolTipProperty); attachToolTipListener(viewComponent, connector.getRenderingConnector()); IView<JComponent> view = constructView(viewComponent, viewDescriptor, connector); GridBagLayout layout = new GridBagLayout(); viewComponent.setLayout(layout); int currentX = 0; int extraRowOffset = 0; int currentY = 0; boolean isSpaceFilled = false; boolean lastRowNeedsFilling = true; List<IView<JComponent>> propertyViews = new ArrayList<>(); int formInset = 2; for (Iterator<IPropertyViewDescriptor> ite = viewDescriptor.getPropertyViewDescriptors().iterator(); ite.hasNext(); ) { IPropertyViewDescriptor propertyViewDescriptor = ite.next(); if (isAllowedForClientType(propertyViewDescriptor, actionHandler)) { String propertyName = null; IPropertyDescriptor propertyDescriptor = null; IModelDescriptor propertyModelDescriptor = propertyViewDescriptor.getModelDescriptor(); if (propertyModelDescriptor != null) { propertyName = propertyModelDescriptor.getName(); propertyDescriptor = ((IComponentDescriptorProvider<?>) viewDescriptor.getModelDescriptor()) .getComponentDescriptor().getPropertyDescriptor(propertyName); if (propertyDescriptor == null) { throw new ViewException( "Property descriptor [" + propertyName + "] does not exist for model descriptor " + viewDescriptor .getModelDescriptor().getName() + "."); } } IView<JComponent> propertyView = createView(propertyViewDescriptor, actionHandler, locale); propertyView.setParent(view); boolean forbidden = !actionHandler.isAccessGranted(propertyViewDescriptor); if (forbidden) { propertyView.setPeer(createSecurityComponent()); } else { propertyViews.add(propertyView); } if (propertyName != null) { connector.addChildConnector(propertyName, propertyView.getConnector()); } // already handled in createView. // if (propertyViewDescriptor.getReadabilityGates() != null) { // if (propertyViewDescriptor.getWritabilityGates() != null) { JLabel propertyLabel = createFormPropertyLabel(actionHandler, locale, propertyViewDescriptor, propertyDescriptor, propertyView, forbidden); int propertyWidth = propertyViewDescriptor.getWidth(); EHorizontalPosition labelHorizontalPosition = propertyViewDescriptor.getLabelHorizontalPosition(); if (labelHorizontalPosition == null) { labelHorizontalPosition = viewDescriptor.getLabelsHorizontalPosition(); } if (labelHorizontalPosition == null) { labelHorizontalPosition = EHorizontalPosition.LEFT; } if (propertyWidth > viewDescriptor.getColumnCount()) { propertyWidth = viewDescriptor.getColumnCount(); } if (currentX + propertyWidth > viewDescriptor.getColumnCount()) { fillLastRow(viewComponent); currentX = 0; currentY++; currentY += extraRowOffset; extraRowOffset = 0; } // label positioning GridBagConstraints constraints = new GridBagConstraints(); computeLabelGridBagConstraints(viewDescriptor, currentX, currentY, formInset, propertyWidth, labelHorizontalPosition, constraints); if (viewDescriptor.getLabelsPosition() != ELabelPosition.NONE && propertyLabel.getText() != null && propertyLabel.getText().length() > 0) { viewComponent.add(propertyLabel, constraints); } // component positioning computeComponentGridBagConstraints(viewDescriptor, currentX, currentY, formInset, propertyWidth, labelHorizontalPosition, constraints); constraints.weightx = propertyView.getPeer().getPreferredSize().width; if (propertyView.getPeer() instanceof JCheckBox) { constraints.weightx = Toolkit.getDefaultToolkit().getScreenResolution(); } if (isHeightExtensible(propertyViewDescriptor)) { constraints.weighty = 1.0; constraints.fill = GridBagConstraints.BOTH; constraints.gridheight = 2; extraRowOffset = 1; isSpaceFilled = true; if (!ite.hasNext()) { constraints.gridwidth = GridBagConstraints.REMAINDER; lastRowNeedsFilling = false; } } else { constraints.fill = GridBagConstraints.NONE; } viewComponent.add(propertyView.getPeer(), constraints); if (propertyView.getPeer() instanceof JLink<?> && propertyViewDescriptor.getAction() != null) { IView<JComponent> targetView; if (propertyDescriptor instanceof IRelationshipEndPropertyDescriptor) { targetView = propertyView; } else { targetView = view; } Action action = getActionFactory().createAction(propertyViewDescriptor.getAction(), actionHandler, targetView, locale); configurePropertyViewAction(propertyViewDescriptor, action); ((JLink<Action>) propertyView.getPeer()).setTarget(action); } currentX += propertyWidth; } } if (lastRowNeedsFilling) { fillLastRow(viewComponent); } if (!isSpaceFilled) { JPanel filler = createJPanel(); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.weightx = 1.0; constraints.weighty = 1.0; constraints.fill = GridBagConstraints.BOTH; switch (viewDescriptor.getLabelsPosition()) { case ASIDE: constraints.gridy = currentY + 1; constraints.gridwidth = viewDescriptor.getColumnCount() * 2; break; case ABOVE: constraints.gridy = (currentY + 1) * 2; constraints.gridwidth = viewDescriptor.getColumnCount(); break; case NONE: constraints.gridy = currentY + 1; constraints.gridwidth = viewDescriptor.getColumnCount(); break; default: break; } viewComponent.add(filler, constraints); } completePropertyViewsWithDynamicToolTips(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicBackgrounds(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicForegrounds(connector, propertyViews, modelDescriptor); completePropertyViewsWithDynamicFonts(connector, propertyViews, modelDescriptor); if (!viewDescriptor.isWidthResizeable()) { JPanel lefter = new JPanel(new BorderLayout()); lefter.add(viewComponent, BorderLayout.WEST); view.setPeer(lefter); } if (viewDescriptor.isScrollable()) { view.setPeer(applyComponentScrollability(viewComponent, viewDescriptor)); } return view; } private void computeComponentGridBagConstraints(IComponentViewDescriptor viewDescriptor, int currentX, int currentY, int formInset, int propertyWidth, EHorizontalPosition labelHorizontalPosition, GridBagConstraints constraints) { switch (viewDescriptor.getLabelsPosition()) { case ASIDE: switch (labelHorizontalPosition) { case RIGHT: constraints.anchor = GridBagConstraints.EAST; constraints.gridx = currentX * 2; break; case LEFT: default: constraints.anchor = GridBagConstraints.WEST; constraints.gridx = currentX * 2 + 1; break; } constraints.insets = new Insets(formInset, 0, formInset, formInset); constraints.gridwidth = propertyWidth * 2 - 1; break; case ABOVE: constraints.gridy++; constraints.insets = new Insets(0, formInset, 0, formInset); constraints.gridwidth = propertyWidth; constraints.anchor = GridBagConstraints.WEST; break; case NONE: constraints.gridx = currentX; constraints.gridy = currentY; constraints.insets = new Insets(0, formInset, 0, formInset); constraints.gridwidth = propertyWidth; constraints.anchor = GridBagConstraints.WEST; break; default: break; } } private void computeLabelGridBagConstraints(IComponentViewDescriptor viewDescriptor, int currentX, int currentY, int formInset, int propertyWidth, EHorizontalPosition labelHorizontalPosition, GridBagConstraints constraints) { switch (viewDescriptor.getLabelsPosition()) { case ASIDE: constraints.insets = new Insets(formInset, formInset, formInset, formInset); switch (labelHorizontalPosition) { case RIGHT: constraints.anchor = GridBagConstraints.WEST; constraints.gridx = currentX * 2 + propertyWidth * 2 - 1; break; case LEFT: default: constraints.anchor = GridBagConstraints.EAST; constraints.gridx = currentX * 2; break; } constraints.gridy = currentY; break; case ABOVE: constraints.insets = new Insets(formInset, formInset, 0, formInset); constraints.anchor = GridBagConstraints.SOUTHWEST; constraints.gridx = currentX; constraints.gridy = currentY * 2; constraints.gridwidth = propertyWidth; break; case NONE: break; default: break; } } private void completePropertyViewsWithDynamicToolTips(ICompositeValueConnector connector, List<IView<JComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor) { // Compute dynamic tooltips for (IView<JComponent> propertyView : propertyViews) { IPropertyViewDescriptor propertyViewDescriptor = (IPropertyViewDescriptor) propertyView.getDescriptor(); IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); String dynamicToolTipProperty = computePropertyDynamicToolTip(modelDescriptor, propertyViewDescriptor, propertyDescriptor); // Dynamic tooltip if (dynamicToolTipProperty != null) { IValueConnector tooltipConnector = connector.getChildConnector(dynamicToolTipProperty); if (tooltipConnector == null) { tooltipConnector = getConnectorFactory().createValueConnector(dynamicToolTipProperty); connector.addChildConnector(dynamicToolTipProperty, tooltipConnector); } attachToolTipListener(propertyView.getPeer(), tooltipConnector); } } } private void completePropertyViewsWithDynamicBackgrounds(ICompositeValueConnector connector, List<IView<JComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor) { // Compute dynamic background for (IView<JComponent> propertyView : propertyViews) { IPropertyViewDescriptor propertyViewDescriptor = (IPropertyViewDescriptor) propertyView.getDescriptor(); IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); String dynamicBackgroundProperty = computePropertyDynamicBackground(modelDescriptor, propertyViewDescriptor, propertyDescriptor); // Dynamic background if (dynamicBackgroundProperty != null) { IValueConnector backgroundConnector = connector.getChildConnector(dynamicBackgroundProperty); if (backgroundConnector == null) { backgroundConnector = getConnectorFactory().createValueConnector(dynamicBackgroundProperty); connector.addChildConnector(dynamicBackgroundProperty, backgroundConnector); } attachBackgroundListener(propertyView.getPeer(), backgroundConnector); } } } private void completePropertyViewsWithDynamicForegrounds(ICompositeValueConnector connector, List<IView<JComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor) { // Compute dynamic foreground for (IView<JComponent> propertyView : propertyViews) { IPropertyViewDescriptor propertyViewDescriptor = (IPropertyViewDescriptor) propertyView.getDescriptor(); IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); String dynamicForegroundProperty = computePropertyDynamicForeground(modelDescriptor, propertyViewDescriptor, propertyDescriptor); // Dynamic foreground if (dynamicForegroundProperty != null) { IValueConnector foregroundConnector = connector.getChildConnector(dynamicForegroundProperty); if (foregroundConnector == null) { foregroundConnector = getConnectorFactory().createValueConnector(dynamicForegroundProperty); connector.addChildConnector(dynamicForegroundProperty, foregroundConnector); } attachForegroundListener(propertyView.getPeer(), foregroundConnector); } } } private void completePropertyViewsWithDynamicFonts(ICompositeValueConnector connector, List<IView<JComponent>> propertyViews, IComponentDescriptor<?> modelDescriptor) { // Compute dynamic font for (IView<JComponent> propertyView : propertyViews) { IPropertyViewDescriptor propertyViewDescriptor = (IPropertyViewDescriptor) propertyView.getDescriptor(); IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); String dynamicFontProperty = computePropertyDynamicFont(modelDescriptor, propertyViewDescriptor, propertyDescriptor); // Dynamic font if (dynamicFontProperty != null) { IValueConnector fontConnector = connector.getChildConnector(dynamicFontProperty); if (fontConnector == null) { fontConnector = getConnectorFactory().createValueConnector(dynamicFontProperty); connector.addChildConnector(dynamicFontProperty, fontConnector); } attachFontListener(propertyView.getPeer(), fontConnector); } } } /** * Attaches a dynamic tooltip listener. * * @param viewComponent * the view component to attach the tooltip to * @param connector * the view connector responsible for the tooltip. */ protected void attachToolTipListener(final JComponent viewComponent, IValueConnector connector) { // Special toolTip handling if (connector != null) { connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { if (evt.getNewValue() != null) { viewComponent.setToolTipText(evt.getNewValue().toString()); } else { viewComponent.setToolTipText(null); } } }); } } /** * Attaches a dynamic background listener. * * @param viewComponent * the view component to attach the background to * @param connector * the view connector responsible for the background. */ protected void attachBackgroundListener(final JComponent viewComponent, IValueConnector connector) { if (connector != null) { connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { if (evt.getNewValue() != null) { viewComponent.setBackground(createColor(evt.getNewValue().toString())); } else { viewComponent.setBackground(null); } } }); } } /** * Attaches a dynamic foreground listener. * * @param viewComponent * the view component to attach the foreground to * @param connector * the view connector responsible for the foreground. */ protected void attachForegroundListener(final JComponent viewComponent, IValueConnector connector) { if (connector != null) { connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { if (evt.getNewValue() != null) { viewComponent.setForeground(createColor(evt.getNewValue().toString())); } else { viewComponent.setForeground(null); } } }); } } /** * Attaches a dynamic font listener. * * @param viewComponent * the view component to attach the font to * @param connector * the view connector responsible for the font. */ protected void attachFontListener(final JComponent viewComponent, IValueConnector connector) { final Font defaultFont = viewComponent.getFont(); if (connector != null) { connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { if (evt.getNewValue() != null) { viewComponent.setFont(createFont(evt.getNewValue().toString(), defaultFont)); } else { viewComponent.setFont(defaultFont); } } }); } } private JLabel createFormPropertyLabel(IActionHandler actionHandler, Locale locale, IPropertyViewDescriptor propertyViewDescriptor, IPropertyDescriptor propertyDescriptor, IView<JComponent> propertyView, boolean forbidden) { JLabel propertyLabel = createPropertyLabel(propertyViewDescriptor, propertyView.getPeer(), actionHandler, locale); if (!propertyViewDescriptor.isReadOnly() && propertyDescriptor != null && propertyDescriptor.isMandatory() && !(propertyDescriptor instanceof IBooleanPropertyDescriptor)) { if (propertyViewDescriptor.getLabelForeground() == null) { propertyLabel.setForeground(createColor(getFormLabelMandatoryPropertyColorHex())); } propertyLabel.setText(decorateMandatoryPropertyLabel(propertyLabel.getText())); } if (forbidden) { propertyLabel.setText(" "); propertyLabel.setIcon(null); } return propertyLabel; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createMapView(IMapViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { BasicMapPanel viewComponent = createMapView(); MapBean mapBean = viewComponent.getMapBean(); mapBean.setScale(100000); MapHandler mapHandler = viewComponent.getMapHandler(); // Add navigation tools over the map mapHandler.add(new EmbeddedNavPanel()); // Add scale display widget over the map mapHandler.add(new EmbeddedScaleDisplayPanel()); // Add MouseDelegator, which handles mouse modes (managing mouse // events) mapHandler.add(new MouseDelegator()); // Add OMMouseMode, which handles how the map reacts to mouse // movements mapHandler.add(new OMMouseMode()); mapHandler.add(new LayerHandler()); MapTileLayer mapTileLayer = new MapTileLayer(); Properties tileProperties = new Properties(); tileProperties.setProperty("rootDir", "http://c.tile.openstreetmap.org/"); mapTileLayer.setProperties(tileProperties); mapTileLayer.setVisible(true); mapHandler.add(mapTileLayer); IModelDescriptor modelDescriptor = viewDescriptor.getModelDescriptor(); String connectorId; if (modelDescriptor instanceof IPropertyDescriptor) { connectorId = modelDescriptor.getName(); } else { connectorId = ModelRefPropertyConnector.THIS_PROPERTY; } IValueConnector connector = new JMapViewConnector(connectorId, mapBean, viewDescriptor.getLongitudeProperty(), viewDescriptor.getLatitudeProperty()); IView<JComponent> view = constructView(viewComponent, viewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected ICompositeView<JComponent> createConstrainedGridView(IConstrainedGridViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JPanel viewComponent = createJPanel(); BasicCompositeView<JComponent> view = constructCompositeView(viewComponent, viewDescriptor); List<IView<JComponent>> childrenViews = new ArrayList<>(); GridBagLayout layout = new GridBagLayout(); viewComponent.setLayout(layout); for (IViewDescriptor childViewDescriptor : viewDescriptor.getChildViewDescriptors()) { IView<JComponent> childView = createView(childViewDescriptor, actionHandler, locale); viewComponent.add(childView.getPeer(), createGridBagConstraints(viewDescriptor.getCellConstraints(childViewDescriptor))); childrenViews.add(childView); } view.setChildren(childrenViews); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createDatePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IDatePropertyDescriptor propertyDescriptor = (IDatePropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector; JComponent viewComponent; TimeZone timeZone = propertyDescriptor.isTimeZoneAware() ? actionHandler.getClientTimeZone() : actionHandler.getReferenceTimeZone(); DateFormat format = createDateFormat(propertyViewDescriptor, propertyDescriptor, timeZone, actionHandler, locale); IFormatter<?, String> formatter = createFormatter(format); if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJDateField(propertyViewDescriptor, locale); ((JDateField) viewComponent).getFormattedTextField().setFormatterFactory( new DefaultFormatterFactory(new DateFormatter(format))); connector = new JDateFieldConnector(propertyDescriptor.getName(), (JDateField) viewComponent); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getDateTemplateValue(propertyDescriptor), Toolkit.getDefaultToolkit().getScreenResolution() / 3); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createDecimalPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IDecimalPropertyDescriptor propertyDescriptor = (IDecimalPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); if (propertyDescriptor instanceof IPercentPropertyDescriptor) { return createPercentPropertyView(propertyViewDescriptor, actionHandler, locale); } IFormatter<Object, String> formatter = createDecimalFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JFormattedFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent, formatter); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getDecimalTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createDurationPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IDurationPropertyDescriptor propertyDescriptor = (IDurationPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JComponent viewComponent; IValueConnector connector; IFormatter<?, String> formatter = createDurationFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JFormattedFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent, formatter); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getDurationTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected JComponent createEmptyComponent() { return createJPanel(); } /** * {@inheritDoc} */ @Override protected IView<JComponent> createEnumerationPropertyView(final IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { final IEnumerationPropertyDescriptor propertyDescriptor = (IEnumerationPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IView<JComponent> view; if (propertyViewDescriptor.isReadOnly()) { IFormatter<?, String> formatter = createEnumerationFormatter(propertyDescriptor, actionHandler, locale); final JLabel viewComponent; if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } IValueConnector connector = new JLabelConnector(propertyDescriptor.getName(), viewComponent); connector.addValueChangeListener(new IValueChangeListener() { @Override public void valueChange(ValueChangeEvent evt) { viewComponent.setIcon(getIconFactory() .getIcon(propertyDescriptor.getIconImageURL(String.valueOf(evt.getNewValue())), getEnumerationIconDimension(propertyViewDescriptor))); } }); ((JLabelConnector) connector).setFormatter(formatter); adjustSizes(propertyViewDescriptor, viewComponent, null, getEnumerationTemplateValue(propertyDescriptor, actionHandler, locale), Toolkit.getDefaultToolkit().getScreenResolution() * 2 / 6); connector.setExceptionHandler(actionHandler); view = constructView(viewComponent, propertyViewDescriptor, connector); } else { if (propertyDescriptor.isLov()) { return createEnumerationReferencePropertyView(propertyViewDescriptor, actionHandler, locale); } else { List<String> enumerationValues = new ArrayList<>(propertyDescriptor.getEnumerationValues()); filterEnumerationValues(enumerationValues, propertyViewDescriptor); if (propertyViewDescriptor instanceof IEnumerationPropertyViewDescriptor && ((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).isRadio()) { IRenderableCompositeValueConnector connector = getConnectorFactory().createCompositeValueConnector( ModelRefPropertyConnector.THIS_PROPERTY, propertyDescriptor.getName()); JPanel viewComponent = createJPanel(); GridLayout layout; switch (((IEnumerationPropertyViewDescriptor) propertyViewDescriptor).getOrientation()) { case HORIZONTAL: layout = new GridLayout(1, 0); break; case VERTICAL: default: layout = new GridLayout(0, 1); } viewComponent.setLayout(layout); List<IView<JComponent>> childrenViews = new ArrayList<>(); for (String enumElement : enumerationValues) { JRadioButton subViewComponent = new JRadioButton(); subViewComponent.setText(propertyDescriptor.getI18nValue(enumElement, actionHandler, locale)); JRadioButtonConnector subConnector = new JRadioButtonConnector(propertyDescriptor.getName(), subViewComponent, enumElement); adjustSizes(propertyViewDescriptor, subViewComponent, null, getEnumerationTemplateValue(propertyDescriptor, actionHandler, locale), Toolkit.getDefaultToolkit().getScreenResolution() * 2 / 6); viewComponent.add(subViewComponent); subConnector.setExceptionHandler(actionHandler); IView<JComponent> subView = constructView(subViewComponent, propertyViewDescriptor, subConnector); connector.addChildConnector(subConnector); childrenViews.add(subView); } view = constructCompositeView(viewComponent, propertyViewDescriptor); ((BasicCompositeView<JComponent>) view).setChildren(childrenViews); connector.setExceptionHandler(actionHandler); view.setConnector(connector); } else { JComboBox<String> viewComponent = createJComboBox(propertyViewDescriptor); if (!propertyDescriptor.isMandatory()) { viewComponent.addItem(null); } for (String enumElement : enumerationValues) { viewComponent.addItem(enumElement); } viewComponent.setRenderer(new TranslatedEnumerationListCellRenderer(propertyDescriptor, getEnumerationIconDimension(propertyViewDescriptor), actionHandler, locale)); adjustSizes(propertyViewDescriptor, viewComponent, null, getEnumerationTemplateValue(propertyDescriptor, actionHandler, locale), getEnumerationIconDimension(propertyViewDescriptor).getWidth()/*Toolkit.getDefaultToolkit() .getScreenResolution() * 3 / 5*/); IValueConnector connector = new JComboBoxConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); view = constructView(viewComponent, propertyViewDescriptor, connector); } } } return view; } /** * {@inheritDoc} */ @Override protected ICompositeView<JComponent> createEvenGridView(IEvenGridViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JPanel viewComponent = createJPanel(); BasicCompositeView<JComponent> view = constructCompositeView(viewComponent, viewDescriptor); List<IView<JComponent>> childrenViews = new ArrayList<>(); GridLayout layout = new GridLayout(); switch (viewDescriptor.getDrivingDimension()) { case ROW: layout.setColumns(viewDescriptor.getDrivingDimensionCellCount()); layout.setRows(0); break; case COLUMN: layout.setRows(viewDescriptor.getDrivingDimensionCellCount()); layout.setColumns(0); break; default: break; } layout.setHgap(5); layout.setVgap(5); viewComponent.setLayout(layout); for (IViewDescriptor childViewDescriptor : viewDescriptor.getChildViewDescriptors()) { IView<JComponent> childView = createView(childViewDescriptor, actionHandler, locale); viewComponent.add(childView.getPeer()); childrenViews.add(childView); } view.setChildren(childrenViews); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createHtmlPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IHtmlPropertyDescriptor propertyDescriptor = (IHtmlPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isReadOnly()) { JTextPane htmlPane = createJTextPane(propertyViewDescriptor); JTextPaneConnector textPaneConnector = new JTextPaneConnector(propertyDescriptor.getName(), htmlPane); JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(htmlPane); if (propertyViewDescriptor instanceof IScrollableViewDescriptor) { if (((IScrollableViewDescriptor) propertyViewDescriptor).isHorizontallyScrollable()) { JPanel noWrapPanel = createJPanel(); noWrapPanel.setLayout(new BorderLayout()); noWrapPanel.add(htmlPane, BorderLayout.CENTER); scrollPane.setViewportView(noWrapPanel); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); } else { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); } if (((IScrollableViewDescriptor) propertyViewDescriptor).isVerticallyScrollable()) { scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); } else { scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); } } else { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); } viewComponent = scrollPane; connector = textPaneConnector; } else { JHTMLEditor htmlEditor = createJHTMLEditor(propertyViewDescriptor, locale); JHTMLEditorConnector htmlEditorConnector = new JHTMLEditorConnector(propertyDescriptor.getName(), htmlEditor); if (propertyViewDescriptor instanceof IScrollableViewDescriptor) { if (((IScrollableViewDescriptor) propertyViewDescriptor).isHorizontallyScrollable()) { htmlEditor.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); } else { htmlEditor.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); } if (((IScrollableViewDescriptor) propertyViewDescriptor).isVerticallyScrollable()) { htmlEditor.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); } else { htmlEditor.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); } } else { htmlEditor.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); htmlEditor.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); } viewComponent = htmlEditor; connector = htmlEditorConnector; } connector.setExceptionHandler(actionHandler); return constructView(viewComponent, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") @Override protected IView<JComponent> createImagePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { final IPropertyDescriptor propertyDescriptor = (IPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); if (propertyViewDescriptor.isReadOnly() || propertyViewDescriptor instanceof IImageViewDescriptor || !(propertyDescriptor instanceof IBinaryPropertyDescriptor)) { JLabel imageLabel; if (propertyViewDescriptor.getAction() != null) { imageLabel = createJLink(propertyViewDescriptor); } else { imageLabel = createJLabel(propertyViewDescriptor, false); } Integer scaledWidth = null; Integer scaledHeight = null; if (propertyViewDescriptor instanceof IScalableImageAware) { scaledWidth = ((IScalableImageAware) propertyViewDescriptor).getScaledWidth(); scaledHeight = ((IScalableImageAware) propertyViewDescriptor).getScaledHeight(); } else if (propertyDescriptor instanceof IScalableImageAware) { scaledWidth = ((IScalableImageAware) propertyDescriptor).getScaledWidth(); scaledHeight = ((IScalableImageAware) propertyDescriptor).getScaledHeight(); } JImageConnector connector = new JImageConnector(propertyViewDescriptor.getModelDescriptor().getName(), imageLabel, scaledWidth, scaledHeight); connector.setExceptionHandler(actionHandler); JPanel viewComponent = createJPanel(); BorderLayout layout = new BorderLayout(); viewComponent.setLayout(layout); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if ((propertyViewDescriptor instanceof IScrollableViewDescriptor) && ((IScrollableViewDescriptor) propertyViewDescriptor).isScrollable()) { imageLabel.setHorizontalAlignment(SwingConstants.LEFT); imageLabel.setVerticalAlignment(SwingConstants.TOP); JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(imageLabel); viewComponent.add(scrollPane, BorderLayout.CENTER); } else { imageLabel.setHorizontalAlignment(SwingConstants.CENTER); imageLabel.setVerticalAlignment(SwingConstants.CENTER); viewComponent.add(imageLabel, BorderLayout.CENTER); } if (imageLabel instanceof JLink<?>) { ((JLink<Action>) imageLabel).setTarget( getActionFactory().createAction(propertyViewDescriptor.getAction(), actionHandler, view, locale)); } return view; } else { return createBinaryPropertyView(propertyViewDescriptor, actionHandler, locale); } } /** * {@inheritDoc} */ @Override protected IView<JComponent> createStaticTextPropertyView(IStaticTextViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isMultiLine()) { viewComponent = createJTextPane(propertyViewDescriptor); connector = new JTextPaneConnector(null, (JTextPane) viewComponent); } else { viewComponent = createJLabel(propertyViewDescriptor, false); connector = new JLabelConnector(null, (JLabel) viewComponent); } connector.setExceptionHandler(actionHandler); connector.setConnectorValue(actionHandler.getTranslation(propertyViewDescriptor.getI18nTextKey(), locale)); IView<JComponent> propertyView = constructView(viewComponent, propertyViewDescriptor, connector); return propertyView; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createIntegerPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IIntegerPropertyDescriptor propertyDescriptor = (IIntegerPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IFormatter<?, String> formatter = createIntegerFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JFormattedFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent, formatter); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getIntegerTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates an action field. * * @param viewDescriptor * the component view descriptor. * @param showTextField * is the text field visible to the user. * @return the created action field. */ protected JActionField createJActionField(IPropertyViewDescriptor viewDescriptor, boolean showTextField) { return new JActionField(showTextField); } /** * Creates a button. * * @return the created button. */ protected JButton createJButton() { JButton button = new JButton(); SwingUtil.configureButton(button); return button; } /** * Creates a button. * * @return the created button. */ protected JComboButton createJComboButton() { JComboButton button = new JComboButton(true); SwingUtil.configureButton(button); return button; } /** * Creates a check box. * * @param viewDescriptor * the component view descriptor. * @return the created check box. */ protected JCheckBox createJCheckBox(IPropertyViewDescriptor viewDescriptor) { return new JCheckBox(); } /** * Creates a radio button. * * @param viewDescriptor * the component view descriptor. * @return the created radio button. */ protected JRadioButton createJRadioButton(IPropertyViewDescriptor viewDescriptor) { return new JRadioButton(); } /** * Creates a tri-state check box. * * @param viewDescriptor * the component view descriptor. * @return the created tri-state check box. */ protected JCheckBox createJTriStateCheckBox(IPropertyViewDescriptor viewDescriptor) { return new JTriStateCheckBox(); } /** * Creates an color picker. * * @param viewDescriptor * the component view descriptor. * @return the created color picker. */ protected JColorPicker createJColorPicker(IPropertyViewDescriptor viewDescriptor) { return new JColorPicker(); } /** * Creates a combo box. * * @param viewDescriptor * the component view descriptor. * @return the created combo box. */ @SuppressWarnings("unchecked") protected JComboBox<String> createJComboBox(IPropertyViewDescriptor viewDescriptor) { return new JComboBox<>(); } /** * Creates a date field. * * @param viewDescriptor * the component view descriptor. * @param locale * the user locale. * @return the created date field. */ protected JDateField createJDateField(IPropertyViewDescriptor viewDescriptor, Locale locale) { JDateField dateField = new JDateField(locale); return dateField; } /** * Creates a JEdit text area. * * @param viewDescriptor * the component view descriptor. * @param language * the language to add syntax highlighting for. * @return the created text area. */ protected JEditTextArea createJEditTextArea(IPropertyViewDescriptor viewDescriptor, String language) { JEditTextArea textArea = new JEditTextArea(); try { textArea.setTokenMarker( (TokenMarker) Class.forName("org.syntax.jedit.tokenmarker." + language + "TokenMarker").newInstance()); } catch (InstantiationException | ClassNotFoundException | IllegalAccessException ex) { // Nothing to do. just don't colorize. } return textArea; } /** * Creates an HTML editor. * * @param viewDescriptor * the component view descriptor. * @param locale * the locale to create the HTML editor for. * @return the created HTML editor. */ protected JHTMLEditor createJHTMLEditor(IPropertyViewDescriptor viewDescriptor, Locale locale) { JHTMLEditor htmlEditor = new JHTMLEditor(locale); return htmlEditor; } /** * Creates a label. * * @param viewDescriptor * the component view descriptor. * @param bold * make it bold ? * @return the created label. */ protected JLabel createJLabel(IPropertyViewDescriptor viewDescriptor, boolean bold) { // To have preferred height computed. JLabel label = new JLabel(" "); if (bold) { label.setFont(createFont(BOLD_FONT, label.getFont())); } return label; } /** * Creates a map view. * * @return the created map view. */ protected BasicMapPanel createMapView() { return new OverlayMapPanel(); } /** * Created an action link. * * @param viewDescriptor * the component view descriptor. * @return the created action link. */ protected JLink<Action> createJLink(IPropertyViewDescriptor viewDescriptor) { // To have preferred height computed. JLink<Action> actionLink = new JLink<>(" ", null, ""); actionLink.addLinkListener(new LinkListener<Action>() { @Override public boolean linkActivated(JLink<Action> link, Action target) { if (target != null) { if (target.isEnabled()) { ActionEvent ae = new ActionEvent(link, ActionEvent.ACTION_PERFORMED, null); target.actionPerformed(ae); } } return false; } }); return actionLink; } /** * Creates a list. * * @param viewDescriptor * the component view descriptor. * @return the created list. */ @SuppressWarnings("unchecked") protected JList<IValueConnector> createJList(IListViewDescriptor viewDescriptor) { JList<IValueConnector> list = new JList<>(); list.setDragEnabled(true); return list; } /** * Creates a menu item. * * @return the created menu item. */ protected JMenuItem createJMenuItem() { return new JMenuItem(); } /** * Creates a panel. * * @return the created panel. */ protected JScrollablePanel createJPanel() { JScrollablePanel panel = new JScrollablePanel(); return panel; } /** * Creates a password field. * * @param viewDescriptor * the component view descriptor. * @return the created password field. */ protected JPasswordField createJPasswordField(IPropertyViewDescriptor viewDescriptor) { JPasswordField passwordField = new JPasswordField(); return passwordField; } /** * Creates a popup menu. * * @return the created popup menu. */ protected JPopupMenu createJPopupMenu() { return new JPopupMenu(); } /** * Creates a scroll pane. * * @return the created scroll pane. */ protected JScrollPane createJScrollPane() { JScrollPane scrollPane = new JScrollPane(); return scrollPane; } /** * Creates a split pane. * * @param viewDescriptor * the component view descriptor. * @return the created split pane. */ protected JSplitPane createJSplitPane(ISplitViewDescriptor viewDescriptor) { JSplitPane splitPane = new JSplitPane(); splitPane.setContinuousLayout(true); splitPane.setOneTouchExpandable(true); return splitPane; } /** * Creates a tabbed pane. * * @param viewDescriptor * the component view descriptor. * @return the created tabbed pane. */ protected JTabbedPane createJTabbedPane(ITabViewDescriptor viewDescriptor) { return new JTabbedPane(); } /** * Creates a table. * * @param viewDescriptor * the component view descriptor. * @return the created table. */ protected JTable createJTable(ITableViewDescriptor viewDescriptor) { JTable table = new JTable() { private static final long serialVersionUID = -2766744091893464462L; /** * Override this method to fix a bug in the JVM which causes the table to * start editing when a mnemonic key or function key is pressed. */ @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { if (SwingUtilities.getUIInputMap(this, condition) != null && SwingUtilities.getUIInputMap(this, condition).get( ks) != null) { return super.processKeyBinding(ks, e, condition, pressed); } /** * ignore all keys that have not been registered */ if (getInputMap(condition).get(ks) != null) { return false; } boolean foundInAncestors = false; JComponent parent = null; if (getParent() instanceof JComponent) { parent = (JComponent) getParent(); } while (!foundInAncestors && parent != null) { if (parent.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(ks) != null) { foundInAncestors = true; } if (parent.getParent() instanceof JComponent) { parent = (JComponent) parent.getParent(); } else { parent = null; } } if (!foundInAncestors) { return super.processKeyBinding(ks, e, condition, pressed); } return false; } }; table.setSurrendersFocusOnKeystroke(true); // There is a bug regarding editing table when drag is enabled. // table.setDragEnabled(true); table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); return table; } /** * Creates a text area. * * @param viewDescriptor * the component view descriptor. * @return the created text area. */ protected JTextArea createJTextArea(IPropertyViewDescriptor viewDescriptor) { JTextArea textArea = new JTextArea(); textArea.setDragEnabled(true); textArea.setWrapStyleWord(true); return textArea; } /** * Creates a text field. * * @param viewDescriptor * the component view descriptor. * @return the created text field. */ protected JTextField createJTextField(IPropertyViewDescriptor viewDescriptor) { JTextField textField = new JTextField(); textField.getDocument().putProperty("filterNewlines", Boolean.FALSE); SwingUtil.enableSelectionOnFocusGained(textField); return textField; } /** * Creates a text pane. * * @param viewDescriptor * the component view descriptor. * @return the created text pane. */ protected JTextPane createJTextPane(IPropertyViewDescriptor viewDescriptor) { JTextPane textPane = new JTextPane(); textPane.setEditorKit(new HTMLEditorKit()); textPane.setDragEnabled(true); return textPane; } /** * Creates a tool bar. * * @return the created tool bar. */ protected JToolBar createJToolBar() { JToolBar toolBar = new JToolBar(); toolBar.setRollover(true); toolBar.setFloatable(true); toolBar.setBorder(BorderFactory.createRaisedBevelBorder()); return toolBar; } /** * Creates a tree. * * @param viewDescriptor * the component view descriptor. * @return the created tree. */ protected JTree createJTree(ITreeViewDescriptor viewDescriptor) { JTree tree = new JTree(); tree.setDragEnabled(true); return tree; } /** * {@inheritDoc} */ @SuppressWarnings("MagicConstant") @Override protected IView<JComponent> createListView(IListViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICollectionDescriptorProvider<?> modelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getModelDescriptor()); IComponentDescriptor<?> rowDescriptor = modelDescriptor.getCollectionDescriptor().getElementDescriptor(); ICompositeValueConnector rowConnectorPrototype = getConnectorFactory().createCompositeValueConnector( modelDescriptor.getName() + "Element", rowDescriptor.getToHtmlProperty()); if (rowConnectorPrototype instanceof AbstractCompositeValueConnector) { ((AbstractCompositeValueConnector) rowConnectorPrototype).setDisplayIcon(viewDescriptor.getIcon()); ((AbstractCompositeValueConnector) rowConnectorPrototype).setIconImageURLProvider( viewDescriptor.getIconImageURLProvider()); } ICollectionConnector connector = getConnectorFactory().createCollectionConnector(modelDescriptor.getName(), getMvcBinder(), rowConnectorPrototype); JList<IValueConnector> viewComponent = createJList(viewDescriptor); JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(viewComponent); IView<JComponent> view = constructView(scrollPane, viewDescriptor, connector); if (viewDescriptor.getRenderedProperty() != null) { IValueConnector cellConnector = createListConnector(viewDescriptor.getRenderedProperty(), rowDescriptor); rowConnectorPrototype.addChildConnector(viewDescriptor.getRenderedProperty(), cellConnector); } viewComponent.setCellRenderer(new EvenOddListCellRenderer(getIconFactory(), viewDescriptor.getRenderedProperty(), viewDescriptor.isDisplayIcon())); viewComponent.setModel(new CollectionConnectorListModel(connector)); viewComponent.setSelectionMode(getSelectionMode(viewDescriptor)); listSelectionModelBinder.bindSelectionModel(viewComponent, connector, viewComponent.getSelectionModel(), null); if (viewDescriptor.getRowAction() != null) { final Action rowAction = getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale); viewComponent.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { ActionEvent ae = new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers()); rowAction.actionPerformed(ae); } } }); } return view; } /** * {@inheritDoc} */ @SuppressWarnings("MagicConstant") @Override protected IView<JComponent> createRepeaterView(IRepeaterViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICollectionDescriptorProvider<?> modelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getModelDescriptor()); IView<JComponent> repeated = createView(viewDescriptor.getRepeatedViewDescriptor(), actionHandler, locale); ICompositeValueConnector elementConnectorPrototype = (ICompositeValueConnector) repeated.getConnector(); ICollectionConnector connector = getConnectorFactory().createCollectionConnector(modelDescriptor.getName(), getMvcBinder(), elementConnectorPrototype); JScrollablePanel repeaterContainer = createJPanel(); repeaterContainer.setScrollableTracksViewportWidth(true); repeaterContainer.setLayout(new BoxLayout(repeaterContainer, BoxLayout.PAGE_AXIS)); JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(repeaterContainer); IView<JComponent> view = constructView(scrollPane, viewDescriptor, connector); Action rowAction = null; if (viewDescriptor.getRowAction() != null) { rowAction = getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale); } new JRepeater(repeaterContainer, viewDescriptor.getRepeatedViewDescriptor(), connector, this, getMvcBinder(), rowAction, actionHandler, locale); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createPasswordPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IPasswordPropertyDescriptor propertyDescriptor = (IPasswordPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JPasswordField viewComponent = createJPasswordField(propertyViewDescriptor); JPasswordFieldConnector connector = new JPasswordFieldConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); adjustSizes(propertyViewDescriptor, viewComponent, null, getStringTemplateValue(propertyDescriptor)); return constructView(viewComponent, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @Override protected IView<JComponent> createPercentPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IPercentPropertyDescriptor propertyDescriptor = (IPercentPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); IFormatter<?, String> formatter = createPercentFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JPercentFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent, formatter); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getPercentTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * Creates a property label. * * @param propertyViewDescriptor * the property view descriptor. * @param propertyComponent * the property component. * @param translationProvider * the translation provider. * @param locale * the locale. * @return the created property label. */ protected JLabel createPropertyLabel(IPropertyViewDescriptor propertyViewDescriptor, JComponent propertyComponent, ITranslationProvider translationProvider, Locale locale) { JLabel propertyLabel = createJLabel(propertyViewDescriptor, false); String labelText = propertyViewDescriptor.getI18nName(translationProvider, locale); propertyLabel.setText(labelText); propertyLabel.setLabelFor(propertyComponent); configurePropertyLabel(propertyLabel, propertyViewDescriptor); return propertyLabel; } private void configurePropertyLabel(JLabel propertyLabel, IPropertyViewDescriptor propertyViewDescriptor) { if (propertyViewDescriptor.getLabelFont() != null) { propertyLabel.setFont(createFont(propertyViewDescriptor.getLabelFont(), propertyLabel.getFont())); } if (propertyViewDescriptor.getLabelForeground() != null) { propertyLabel.setForeground(createColor(propertyViewDescriptor.getLabelForeground())); } if (propertyViewDescriptor.getLabelBackground() != null) { propertyLabel.setBackground(createColor(propertyViewDescriptor.getLabelBackground())); } if (propertyViewDescriptor.getIcon() != null) { propertyLabel.setIcon( getIconFactory().getIcon(propertyViewDescriptor.getIcon(), getIconFactory().getTinyIconSize())); } } /** * {@inheritDoc} */ @Override protected IView<JComponent> createReferencePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IReferencePropertyDescriptor<?> propertyDescriptor = (IReferencePropertyDescriptor<?>) propertyViewDescriptor .getModelDescriptor(); JComponent viewComponent; IValueConnector connector; String renderedProperty = computeRenderedProperty(propertyViewDescriptor); if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName() + "." + renderedProperty, (JLabel) viewComponent); } else { viewComponent = createJActionField(propertyViewDescriptor, true); connector = new JReferenceFieldConnector(propertyDescriptor.getName(), (JActionField) viewComponent); ((JReferenceFieldConnector) connector).setRenderingConnector(new BasicValueConnector(renderedProperty)); } adjustSizes(propertyViewDescriptor, viewComponent, null, null); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if (viewComponent instanceof JActionField) { if (propertyViewDescriptor instanceof IReferencePropertyViewDescriptor) { ((JActionField) viewComponent).setFieldEditable( ((IReferencePropertyViewDescriptor) propertyViewDescriptor).isAutoCompleteEnabled()); } Action lovAction = createLovAction(view, actionHandler, locale); // lovAction.putValue(Action.NAME, // actionHandler.getTranslation( // "lov.element.name", // new Object[] {propertyDescriptor.getReferencedDescriptor().getI18nName( // actionHandler, locale)}, locale)); lovAction.putValue(Action.SHORT_DESCRIPTION, actionHandler.getTranslation("lov.element.description", new Object[]{propertyDescriptor.getReferencedDescriptor().getI18nName(actionHandler, locale)}, locale) + IActionFactory.TOOLTIP_ELLIPSIS); if (propertyDescriptor.getReferencedDescriptor().getIcon() != null) { lovAction.putValue(Action.SMALL_ICON, getIconFactory() .getIcon(propertyDescriptor.getReferencedDescriptor().getIcon(), getIconFactory().getTinyIconSize())); } ((JActionField) viewComponent).setActions(Collections.singletonList(lovAction)); if (propertyViewDescriptor instanceof IStringPropertyViewDescriptor) { attachCharAction(view, ((JActionField) viewComponent).getTextField(), ((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction(), actionHandler, locale); } } return view; } /** * Creates a security panel. * * @return the created security panel. */ @Override protected JPanel createSecurityComponent() { JPanel panel = createJPanel(); panel.setLayout(new BorderLayout()); return panel; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createSourceCodePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { ISourceCodePropertyDescriptor propertyDescriptor = (ISourceCodePropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JEditTextArea viewComponent = createJEditTextArea(propertyViewDescriptor, propertyDescriptor.getLanguage()); JEditTextAreaConnector connector = new JEditTextAreaConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); return constructView(viewComponent, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @Override protected ICompositeView<JComponent> createSplitView(ISplitViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { JSplitPane viewComponent = createJSplitPane(viewDescriptor); BasicCompositeView<JComponent> view = constructCompositeView(viewComponent, viewDescriptor); List<IView<JComponent>> childrenViews = new ArrayList<>(); switch (viewDescriptor.getOrientation()) { case HORIZONTAL: viewComponent.setOrientation(JSplitPane.HORIZONTAL_SPLIT); break; case VERTICAL: viewComponent.setOrientation(JSplitPane.VERTICAL_SPLIT); break; default: break; } if (viewDescriptor.getLeftTopViewDescriptor() != null) { IView<JComponent> leftTopView = createView(viewDescriptor.getLeftTopViewDescriptor(), actionHandler, locale); viewComponent.setLeftComponent(leftTopView.getPeer()); childrenViews.add(leftTopView); } if (viewDescriptor.getRightBottomViewDescriptor() != null) { IView<JComponent> rightBottomView = createView(viewDescriptor.getRightBottomViewDescriptor(), actionHandler, locale); viewComponent.setRightComponent(rightBottomView.getPeer()); rightBottomView.getPeer().setMinimumSize(new Dimension(0, 0)); childrenViews.add(rightBottomView); } view.setChildren(childrenViews); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createStringPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { IStringPropertyDescriptor propertyDescriptor = (IStringPropertyDescriptor) propertyViewDescriptor .getModelDescriptor(); JComponent viewComponent; IValueConnector connector; if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JTextFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent); } adjustSizes(propertyViewDescriptor, viewComponent, null, getStringTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); if (viewComponent instanceof JTextComponent && propertyViewDescriptor instanceof IStringPropertyViewDescriptor) { attachCharAction(view, (JTextComponent) viewComponent, ((IStringPropertyViewDescriptor) propertyViewDescriptor).getCharacterAction(), actionHandler, locale); } return view; } /** * Creates a table cell renderer for a given property descriptor. * * @param propertyDescriptor * the property descriptor to create the renderer for. * @param propertyViewDescriptor * the property view descriptor * @param actionHandler * the action handler. * @param locale * the locale. * @return the created table cell renderer. */ protected TableCellRenderer createTableCellRenderer(IPropertyDescriptor propertyDescriptor, IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { TableCellRenderer cellRenderer = null; if (propertyDescriptor instanceof IBooleanPropertyDescriptor) { cellRenderer = createBooleanTableCellRenderer((IBooleanPropertyDescriptor) propertyDescriptor, locale); } else if (propertyDescriptor instanceof IDatePropertyDescriptor) { TimeZone timeZone = ((IDatePropertyDescriptor) propertyDescriptor).isTimeZoneAware() ? actionHandler.getClientTimeZone() : actionHandler.getReferenceTimeZone(); cellRenderer = createDateTableCellRenderer(propertyViewDescriptor, (IDatePropertyDescriptor) propertyDescriptor, timeZone, actionHandler, locale); } else if (propertyDescriptor instanceof ITimePropertyDescriptor) { cellRenderer = createTimeTableCellRenderer(propertyViewDescriptor, (ITimePropertyDescriptor) propertyDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IDurationPropertyDescriptor) { cellRenderer = createDurationTableCellRenderer(propertyViewDescriptor, (IDurationPropertyDescriptor) propertyDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IEnumerationPropertyDescriptor) { org.jspresso.framework.util.gui.Dimension iconSize = getEnumerationIconDimension(propertyViewDescriptor); cellRenderer = createEnumerationTableCellRenderer((IEnumerationPropertyDescriptor) propertyDescriptor, iconSize, actionHandler, locale); } else if (propertyDescriptor instanceof INumberPropertyDescriptor) { cellRenderer = createNumberTableCellRenderer(propertyViewDescriptor, (INumberPropertyDescriptor) propertyDescriptor, actionHandler, locale); } else if (propertyDescriptor instanceof IRelationshipEndPropertyDescriptor) { cellRenderer = createRelationshipEndTableCellRenderer((IRelationshipEndPropertyDescriptor) propertyDescriptor, locale); } else if (propertyDescriptor instanceof IBinaryPropertyDescriptor) { cellRenderer = createBinaryTableCellRenderer((IBinaryPropertyDescriptor) propertyDescriptor, propertyViewDescriptor); } else if (propertyDescriptor instanceof IStringPropertyDescriptor) { cellRenderer = createStringTableCellRenderer((IStringPropertyDescriptor) propertyDescriptor, locale); } else if (propertyDescriptor instanceof IColorPropertyDescriptor) { cellRenderer = createColorTableCellRenderer((IColorPropertyDescriptor) propertyDescriptor, locale); } return cellRenderer; } /** * {@inheritDoc} */ @Override protected JComponent decorateWithPaginationView(JComponent viewPeer, JComponent paginationViewPeer) { JPanel decorator = new JPanel(new BorderLayout()); decorator.add(viewPeer, BorderLayout.CENTER); decorator.add(paginationViewPeer, BorderLayout.SOUTH); return decorator; } /** * {@inheritDoc} */ @SuppressWarnings({"ConstantConditions", "MagicConstant"}) @Override protected IView<JComponent> createTableView(ITableViewDescriptor viewDescriptor, final IActionHandler actionHandler, Locale locale) { ICollectionDescriptorProvider<?> modelDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor .getModelDescriptor()); IComponentDescriptor<?> rowDescriptor = modelDescriptor.getCollectionDescriptor().getElementDescriptor(); ICompositeValueConnector rowConnectorPrototype = getConnectorFactory().createCompositeValueConnector( modelDescriptor.getName() + "Element", rowDescriptor.getToHtmlProperty()); ICollectionConnector connector = getConnectorFactory().createCollectionConnector(modelDescriptor.getName(), getMvcBinder(), rowConnectorPrototype); JTable viewComponent = createJTable(viewDescriptor); viewComponent.getTableHeader().setReorderingAllowed(viewDescriptor.isColumnReorderingAllowed()); JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(viewComponent); JLabel iconLabel = new JLabel(); iconLabel.setIcon(getIconFactory().getIcon(rowDescriptor.getIcon(), getIconFactory().getTinyIconSize())); iconLabel.setBorder(BorderFactory.createLoweredBevelBorder()); scrollPane.setCorner(ScrollPaneConstants.UPPER_TRAILING_CORNER, iconLabel); IView<JComponent> view = constructView(scrollPane, viewDescriptor, connector); if (viewDescriptor.isHorizontallyScrollable()) { viewComponent.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); } else { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); } List<Class<?>> columnClasses = new ArrayList<>(); Set<String> forbiddenColumns = new HashSet<>(); Map<IPropertyViewDescriptor, Object[]> userColumnViewDescriptors = getUserColumnViewDescriptors(viewDescriptor, actionHandler); for (Map.Entry<IPropertyViewDescriptor, Object[]> columnViewDescriptorEntry : userColumnViewDescriptors .entrySet()) { IPropertyViewDescriptor columnViewDescriptor = columnViewDescriptorEntry.getKey(); String columnId = columnViewDescriptor.getModelDescriptor().getName(); if (actionHandler.isAccessGranted(columnViewDescriptor)) { try { actionHandler.pushToSecurityContext(columnViewDescriptor); IValueConnector columnConnector = createColumnConnector(columnViewDescriptor, rowDescriptor, actionHandler); if (columnViewDescriptor.getAction() != null && !columnViewDescriptor.isReadOnly()) { // We must listen for incoming connector value change to trigger the // action. columnConnector.addValueChangeListener( new ConnectorActionAdapter<>(columnViewDescriptor.getAction(), getActionFactory(), actionHandler, view)); } String propertyName = columnViewDescriptor.getModelDescriptor().getName(); rowConnectorPrototype.addChildConnector(propertyName, columnConnector); columnClasses.add(rowDescriptor.getPropertyDescriptor(columnId).getModelType()); // already handled in createColumnConnector // if (columnViewDescriptor.getReadabilityGates() != null) { // if (columnViewDescriptor.getWritabilityGates() != null) { } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } else { // The column simply won't be added. forbiddenColumns.add(columnId); } } List<String> columnConnectorKeys = new ArrayList<>(rowConnectorPrototype.getChildConnectorKeys()); // remove row rendering connector id columnConnectorKeys.remove(0); CollectionConnectorTableModel tableModel = new CollectionConnectorTableModel(connector, columnConnectorKeys, columnClasses); tableModel.setExceptionHandler(actionHandler); setupTableModel(viewDescriptor, actionHandler, connector, viewComponent, tableModel); viewComponent.setSelectionMode(getSelectionMode(viewDescriptor)); int maxColumnSize = computePixelWidth(viewComponent, getMaxColumnCharacterLength()); int columnIndex = 0; for (Map.Entry<IPropertyViewDescriptor, Object[]> columnViewDescriptorEntry : userColumnViewDescriptors .entrySet()) { IPropertyViewDescriptor columnViewDescriptor = columnViewDescriptorEntry.getKey(); String propertyName = columnViewDescriptor.getModelDescriptor().getName(); if (!forbiddenColumns.contains(propertyName)) { configureTableColumn(actionHandler, locale, viewDescriptor, connector, rowConnectorPrototype, viewComponent, view, maxColumnSize, columnIndex, columnViewDescriptorEntry, columnViewDescriptor, propertyName, viewComponent.getModel()); columnIndex++; } } viewComponent.addMouseListener(new PopupListener(viewComponent, view, actionHandler, locale)); int minimumWidth = 0; for (int i = 0; i < 1 && i < viewComponent.getColumnModel().getColumnCount(); i++) { minimumWidth += viewComponent.getColumnModel().getColumn(i).getPreferredWidth(); } scrollPane.setMinimumSize(new Dimension(minimumWidth, viewComponent.getRowHeight() * 6 + viewComponent.getTableHeader().getPreferredSize().height)); if (viewDescriptor.getRowAction() != null) { final Action rowAction = getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale); viewComponent.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { ActionEvent ae = new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers()); rowAction.actionPerformed(ae); } } }); } if (viewDescriptor.getPermId() != null) { viewComponent.getColumnModel().addColumnModelListener( new ColumnPreferencesListener(viewComponent, viewDescriptor.getPermId(), actionHandler)); } String dynamicBackgroundProperty = computeComponentDynamicBackground(viewDescriptor, rowDescriptor); if (dynamicBackgroundProperty != null) { IValueConnector backgroundConnector = rowConnectorPrototype.getChildConnector(dynamicBackgroundProperty); if (backgroundConnector == null) { backgroundConnector = getConnectorFactory().createValueConnector(dynamicBackgroundProperty); rowConnectorPrototype.addChildConnector(dynamicBackgroundProperty, backgroundConnector); } } tableModel.setRowBackgroundProperty(dynamicBackgroundProperty); String dynamicForegroundProperty = computeComponentDynamicForeground(viewDescriptor, rowDescriptor); if (dynamicForegroundProperty != null) { IValueConnector backgroundConnector = rowConnectorPrototype.getChildConnector(dynamicForegroundProperty); if (backgroundConnector == null) { backgroundConnector = getConnectorFactory().createValueConnector(dynamicForegroundProperty); rowConnectorPrototype.addChildConnector(dynamicForegroundProperty, backgroundConnector); } } tableModel.setRowForegroundProperty(dynamicForegroundProperty); String dynamicFontProperty = computeComponentDynamicFont(viewDescriptor, rowDescriptor); if (dynamicFontProperty != null) { IValueConnector backgroundConnector = rowConnectorPrototype.getChildConnector(dynamicFontProperty); if (backgroundConnector == null) { backgroundConnector = getConnectorFactory().createValueConnector(dynamicFontProperty); rowConnectorPrototype.addChildConnector(dynamicFontProperty, backgroundConnector); } } tableModel.setRowFontProperty(dynamicFontProperty); return view; } @SuppressWarnings("ConstantConditions") private void configureTableColumn(final IActionHandler actionHandler, Locale locale, ITableViewDescriptor viewDescriptor, ICollectionConnector connector, ICompositeValueConnector rowConnectorPrototype, final JTable table, final IView<JComponent> view, int maxColumnSize, final int columnIndex, Map.Entry<IPropertyViewDescriptor, Object[]> columnViewDescriptorEntry, IPropertyViewDescriptor columnViewDescriptor, String propertyName, TableModel tableModel) { IComponentDescriptor<?> rowDescriptor = ((ICollectionDescriptorProvider<?>) viewDescriptor.getModelDescriptor()) .getCollectionDescriptor().getElementDescriptor(); TableColumn column = table.getColumnModel().getColumn(columnIndex); column.setIdentifier(computeColumnIdentifier(viewDescriptor, columnViewDescriptor)); IPropertyDescriptor propertyDescriptor = rowDescriptor.getPropertyDescriptor(propertyName); String columnName = columnViewDescriptor.getI18nName(actionHandler, locale); if (!columnViewDescriptor.isReadOnly() && propertyDescriptor.isMandatory() && !(propertyDescriptor instanceof IBooleanPropertyDescriptor)) { columnName = decorateMandatoryPropertyLabel(columnName); } column.setHeaderValue(columnName); IView<JComponent> editorView = createView(columnViewDescriptor, actionHandler, locale); editorView.setParent(view); editorView.getConnector().resetReadabilityGates(); editorView.getConnector().resetWritabilityGates(); for (IValueChangeListener listener : editorView.getConnector().getValueChangeListeners()) { if (listener instanceof ConnectorActionAdapter) { // to avoid the action to be fired by the editor. editorView.getConnector().removeValueChangeListener(listener); } } if (editorView.getConnector().getParentConnector() == null) { editorView.getConnector().setParentConnector(connector); } column.setCellEditor(createTableCellEditor(editorView, actionHandler)); TableCellRenderer cellRenderer = createTableCellRenderer(propertyDescriptor, columnViewDescriptor, actionHandler, locale); if (cellRenderer == null) { cellRenderer = new EvenOddTableCellRenderer(); } if (cellRenderer instanceof JLabel) { configureHorizontalAlignment((JLabel) cellRenderer, columnViewDescriptor.getHorizontalAlignment()); } if (cellRenderer instanceof JComponent) { configureComponent(columnViewDescriptor, actionHandler, locale, (JComponent) cellRenderer); if (cellRenderer instanceof EvenOddTableCellRenderer) { // To preserve font that has been set and avoid JTable changing it. ((EvenOddTableCellRenderer) cellRenderer).setCustomFont(((JComponent) cellRenderer).getFont()); } } if (cellRenderer instanceof DynamicStyleRenderer) { String dynamicToolTipProperty = computePropertyDynamicToolTip(rowDescriptor, columnViewDescriptor, propertyDescriptor); if (dynamicToolTipProperty != null) { IValueConnector toolTipConnector = rowConnectorPrototype.getChildConnector(dynamicToolTipProperty); if (toolTipConnector == null) { toolTipConnector = getConnectorFactory().createValueConnector(dynamicToolTipProperty); rowConnectorPrototype.addChildConnector(dynamicToolTipProperty, toolTipConnector); } } ((DynamicStyleRenderer) cellRenderer).setToolTipProperty(dynamicToolTipProperty); String dynamicBackgroundProperty = computePropertyDynamicBackground(rowDescriptor, columnViewDescriptor, propertyDescriptor); if (dynamicBackgroundProperty != null) { IValueConnector backgroundConnector = rowConnectorPrototype.getChildConnector(dynamicBackgroundProperty); if (backgroundConnector == null) { backgroundConnector = getConnectorFactory().createValueConnector(dynamicBackgroundProperty); rowConnectorPrototype.addChildConnector(dynamicBackgroundProperty, backgroundConnector); } } ((DynamicStyleRenderer) cellRenderer).setBackgroundProperty(dynamicBackgroundProperty); String dynamicForegroundProperty = computePropertyDynamicForeground(rowDescriptor, columnViewDescriptor, propertyDescriptor); if (dynamicForegroundProperty != null) { IValueConnector foregroundConnector = rowConnectorPrototype.getChildConnector(dynamicForegroundProperty); if (foregroundConnector == null) { foregroundConnector = getConnectorFactory().createValueConnector(dynamicForegroundProperty); rowConnectorPrototype.addChildConnector(dynamicForegroundProperty, foregroundConnector); } } ((DynamicStyleRenderer) cellRenderer).setForegroundProperty(dynamicForegroundProperty); String dynamicFontProperty = computePropertyDynamicFont(rowDescriptor, columnViewDescriptor, propertyDescriptor); if (dynamicFontProperty != null) { IValueConnector fontConnector = rowConnectorPrototype.getChildConnector(dynamicFontProperty); if (fontConnector == null) { fontConnector = getConnectorFactory().createValueConnector(dynamicFontProperty); rowConnectorPrototype.addChildConnector(dynamicFontProperty, fontConnector); } } ((DynamicStyleRenderer) cellRenderer).setFontProperty(dynamicFontProperty); } if (columnViewDescriptor.getAction() != null && columnViewDescriptor.isReadOnly()) { Action colAction = getActionFactory().createAction(columnViewDescriptor.getAction(), actionHandler, view, locale); configurePropertyViewAction(columnViewDescriptor, colAction); cellRenderer = new HyperlinkTableCellRenderer(cellRenderer, colAction, columnIndex); table.addMouseListener((MouseListener) cellRenderer); } column.setCellRenderer(cellRenderer); EvenOddTableCellRenderer headerRenderer = new EvenOddTableCellRenderer(); configurePropertyLabel(headerRenderer, columnViewDescriptor); if (propertyDescriptor.isMandatory() && !(propertyDescriptor instanceof IBooleanPropertyDescriptor)) { if (columnViewDescriptor.getLabelForeground() == null) { headerRenderer.setForeground(createColor(getTableHeaderMandatoryPropertyColorHex())); } headerRenderer.setText(decorateMandatoryPropertyLabel(headerRenderer.getText())); } // To preserve font that has been set and avoid JTable changing it. headerRenderer.setCustomFont(headerRenderer.getFont()); String viewDescription = columnViewDescriptor.getI18nDescription(actionHandler, locale); viewDescription = completeDescriptionWithLiveDebugUI(columnViewDescriptor, viewDescription); if (viewDescription != null && viewDescription.length() > 0) { headerRenderer.setToolTipText(viewDescription); } if (tableModel instanceof AbstractTableSorter) { column.setHeaderRenderer( new AbstractTableSorter.SortableHeaderRenderer((AbstractTableSorter) tableModel, headerRenderer)); } else { column.setHeaderRenderer(headerRenderer); } if (columnViewDescriptorEntry.getValue() != null) { column.setPreferredWidth((Integer) columnViewDescriptorEntry.getValue()[0]); } else { if (columnViewDescriptor.getPreferredSize() != null && columnViewDescriptor.getPreferredSize().getWidth() > 0) { column.setPreferredWidth(columnViewDescriptor.getPreferredSize().getWidth()); } else { int minHeaderWidth = computePixelWidth(table, columnName.length()); if (propertyDescriptor instanceof IBooleanPropertyDescriptor || propertyDescriptor instanceof IBinaryPropertyDescriptor) { column.setPreferredWidth(Math.max(computePixelWidth(table, 2), minHeaderWidth)); } else if (propertyDescriptor instanceof IEnumerationPropertyDescriptor) { column.setPreferredWidth(Math.max(editorView.getPeer().getPreferredSize().width, minHeaderWidth)); } else { column.setPreferredWidth(Math.max(Math.min(computePixelWidth(table, getFormatLength(createFormatter(columnViewDescriptor, propertyDescriptor, actionHandler, locale), getTemplateValue(propertyDescriptor))), maxColumnSize), minHeaderWidth)); } } } final IAction focusGainedAction = columnViewDescriptor.getFocusGainedAction(); if (focusGainedAction != null) { table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { @Override public void columnAdded(TableColumnModelEvent e) { // NO-OP } @Override public void columnRemoved(TableColumnModelEvent e) { // NO-OP } @Override public void columnMoved(TableColumnModelEvent e) { // NO-OP } @Override public void columnMarginChanged(ChangeEvent e) { // NO-OP } @Override public void columnSelectionChanged(ListSelectionEvent lse) { handleTableCellSelectionEvent(lse, table, columnIndex, actionHandler, focusGainedAction, view); } }); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent lse) { handleTableCellSelectionEvent(lse, table, columnIndex, actionHandler, focusGainedAction, view); } }); } } private void handleTableCellSelectionEvent(ListSelectionEvent lse, JTable table, int columnIndex, IActionHandler actionHandler, IAction focusGainedAction, IView<JComponent> view) { if (!lse.getValueIsAdjusting()) { int selectedRow = table.getSelectedRow(); int selectedColumn = table.getSelectedColumn(); if (selectedColumn == table.convertColumnIndexToView(columnIndex)) { actionHandler.execute(focusGainedAction, getActionFactory() .createActionContext(actionHandler, view, view.getConnector(), String.valueOf(selectedRow) + ";" + columnIndex, table)); } } } private class ColumnPreferencesListener implements TableColumnModelListener { private final TableColumnModel columnModel; private final String tableId; private final IActionHandler actionHandler; private boolean columnsChanged; /** * Constructs a new {@code ColumnPreferencesListener} instance. * * @param table * the table. * @param tableId * the table id. * @param actionHandler * the action handler. */ public ColumnPreferencesListener(JTable table, String tableId, IActionHandler actionHandler) { this.columnModel = table.getColumnModel(); this.tableId = tableId; this.actionHandler = actionHandler; this.columnsChanged = false; table.getTableHeader().addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { saveColumns(); } }); } @Override public void columnSelectionChanged(ListSelectionEvent e) { // NO-OP. } @Override public void columnRemoved(TableColumnModelEvent e) { // NO-OP. } @Override public void columnMoved(TableColumnModelEvent e) { columnsChanged = true; } @Override public void columnMarginChanged(ChangeEvent e) { columnsChanged = true; } @Override public void columnAdded(TableColumnModelEvent e) { // NO-OP. } private void saveColumns() { if (columnsChanged) { columnsChanged = false; Object[][] columnPrefs = new Object[columnModel.getColumnCount()][2]; for (int i = 0; i < columnModel.getColumnCount(); i++) { Object[] columnPref = new Object[]{columnModel.getColumn(i).getIdentifier(), columnModel.getColumn( i).getWidth()}; columnPrefs[i] = columnPref; } storeTablePreferences(tableId, columnPrefs, actionHandler); } } } private void setupTableModel(ITableViewDescriptor viewDescriptor, IActionHandler actionHandler, ICollectionConnector connector, JTable viewComponent, TableModel tableModel) { if (viewDescriptor.isSortable()) { AbstractTableSorter sorterDecorator; if (viewDescriptor.getSortingAction() != null) { sorterDecorator = new ActionTableSorter(tableModel, viewComponent.getTableHeader(), actionHandler, viewDescriptor.getSortingAction()); } else { sorterDecorator = new TableSorter(tableModel, viewComponent.getTableHeader()); ((TableSorter) sorterDecorator).setColumnComparator(String.class, String.CASE_INSENSITIVE_ORDER); } org.jspresso.framework.util.gui.Dimension iconSize = new org.jspresso.framework.util.gui.Dimension( viewComponent.getTableHeader().getFont().getSize(), viewComponent.getTableHeader().getFont().getSize()); sorterDecorator.setUpIcon(getIconFactory().getUpIcon(iconSize)); sorterDecorator.setDownIcon(getIconFactory().getDownIcon(iconSize)); viewComponent.setModel(sorterDecorator); listSelectionModelBinder.bindSelectionModel(viewComponent, connector, viewComponent.getSelectionModel(), sorterDecorator); } else { viewComponent.setModel(tableModel); listSelectionModelBinder.bindSelectionModel(viewComponent, connector, viewComponent.getSelectionModel(), null); } } /** * {@inheritDoc} */ @Override protected ICompositeView<JComponent> createTabView(final ITabViewDescriptor viewDescriptor, final IActionHandler actionHandler, Locale locale) { final JTabbedPane viewComponent = createJTabbedPane(viewDescriptor); final BasicIndexedView<JComponent> view = constructIndexedView(viewComponent, viewDescriptor); viewComponent.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { JTabbedPane source = (JTabbedPane) e.getSource(); int selectedIndex = source.getSelectedIndex(); view.setCurrentViewIndex(selectedIndex); storeTabSelectionPreference(viewDescriptor, selectedIndex, actionHandler); triggerTabSelectionAction(selectedIndex, source, viewDescriptor, view, actionHandler); } }); List<IView<JComponent>> childrenViews = new ArrayList<>(); for (IViewDescriptor childViewDescriptor : viewDescriptor.getChildViewDescriptors()) { if (actionHandler.isAccessGranted(childViewDescriptor)) { IView<JComponent> childView = createView(childViewDescriptor, actionHandler, locale); Icon childIcon = getIconFactory().getIcon(childViewDescriptor.getIcon(), getIconFactory().getSmallIconSize()); String tabText = childViewDescriptor.getI18nName(actionHandler, locale); ERenderingOptions renderingOptions = getDefaultTabRenderingOptions(); if (viewDescriptor.getRenderingOptions() != null) { renderingOptions = viewDescriptor.getRenderingOptions(); } switch (renderingOptions) { case ICON: tabText = null; break; case LABEL: childIcon = null; break; default: break; } if (childViewDescriptor.getDescription() != null) { viewComponent.addTab(tabText, childIcon, childView.getPeer(), childViewDescriptor.getI18nDescription(actionHandler, locale)); } else { viewComponent.addTab(tabText, childIcon, childView.getPeer()); } childrenViews.add(childView); } } view.setChildren(childrenViews); viewComponent.setSelectedIndex(getTabSelectionPreference(viewDescriptor, actionHandler)); return view; } /** * {@inheritDoc} */ @Override protected void selectChildViewIndex(JComponent viewComponent, int index) { if (viewComponent instanceof JTabbedPane) { ((JTabbedPane) viewComponent).setSelectedIndex(index); } } /** * {@inheritDoc} */ @Override protected IView<JComponent> createTextPropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { ITextPropertyDescriptor propertyDescriptor = (ITextPropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector; JScrollPane scrollPane = createJScrollPane(); JTextArea viewComponent = createJTextArea(propertyViewDescriptor); viewComponent.setLineWrap(true); scrollPane.setViewportView(viewComponent); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); connector = new JTextAreaConnector(propertyDescriptor.getName(), viewComponent); connector.setExceptionHandler(actionHandler); return constructView(scrollPane, propertyViewDescriptor, connector); } /** * {@inheritDoc} */ @Override protected IView<JComponent> createTimePropertyView(IPropertyViewDescriptor propertyViewDescriptor, IActionHandler actionHandler, Locale locale) { ITimePropertyDescriptor propertyDescriptor = (ITimePropertyDescriptor) propertyViewDescriptor.getModelDescriptor(); IValueConnector connector; JComponent viewComponent; IFormatter<?, String> formatter = createTimeFormatter(propertyViewDescriptor, propertyDescriptor, actionHandler, locale); if (propertyViewDescriptor.isReadOnly()) { if (propertyViewDescriptor.getAction() != null) { viewComponent = createJLink(propertyViewDescriptor); } else { viewComponent = createJLabel(propertyViewDescriptor, true); } connector = new JLabelConnector(propertyDescriptor.getName(), (JLabel) viewComponent); ((JLabelConnector) connector).setFormatter(formatter); } else { viewComponent = createJTextField(propertyViewDescriptor); connector = new JFormattedFieldConnector(propertyDescriptor.getName(), (JTextField) viewComponent, formatter); } adjustSizes(propertyViewDescriptor, viewComponent, formatter, getTimeTemplateValue(propertyDescriptor)); connector.setExceptionHandler(actionHandler); IView<JComponent> view = constructView(viewComponent, propertyViewDescriptor, connector); return view; } /** * {@inheritDoc} */ @Override protected IView<JComponent> createTreeView(ITreeViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale) { ICompositeValueConnector connector = createTreeViewConnector(viewDescriptor, actionHandler, locale); final JTree viewComponent = createJTree(viewDescriptor); ConnectorHierarchyTreeModel treeModel = new ConnectorHierarchyTreeModel(connector); viewComponent.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); viewComponent.setModel(treeModel); viewComponent.setCellRenderer(new ConnectorTreeCellRenderer(viewDescriptor.isDisplayIcon())); treeSelectionModelBinder.bindSelectionModel(connector, viewComponent); if (viewDescriptor.isExpanded()) { viewComponent.getModel().addTreeModelListener(new TreeModelListener() { @Override public void treeNodesChanged(TreeModelEvent e) { // NO-OP. } @Override public void treeNodesInserted(TreeModelEvent e) { expandAll(viewComponent, e.getTreePath()); } @Override public void treeNodesRemoved(TreeModelEvent e) { // NO-OP. } @Override public void treeStructureChanged(TreeModelEvent e) { expandAll(viewComponent, e.getTreePath()); } }); } JScrollPane scrollPane = createJScrollPane(); scrollPane.setViewportView(viewComponent); IView<JComponent> view = constructView(scrollPane, viewDescriptor, connector); viewComponent.addMouseListener(new PopupListener(viewComponent, view, actionHandler, locale)); scrollPane.setMinimumSize(TREE_PREFERRED_SIZE); if (viewDescriptor.getRowAction() != null) { final Action rowAction = getActionFactory().createAction(viewDescriptor.getRowAction(), actionHandler, view, locale); viewComponent.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { ActionEvent ae = new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers()); rowAction.actionPerformed(ae); } } }); } return view; } /** * {@inheritDoc} */ @Override protected void decorateWithActions(IViewDescriptor viewDescriptor, IActionHandler actionHandler, Locale locale, IView<JComponent> view) { ActionMap actionMap = viewDescriptor.getActionMap(); ActionMap secondaryActionMap = viewDescriptor.getSecondaryActionMap(); if (actionMap != null || secondaryActionMap != null) { JPanel viewPanel = createJPanel(); viewPanel.setLayout(new BorderLayout()); viewPanel.add(view.getPeer(), BorderLayout.CENTER); boolean asideActions = false; ERenderingOptions defaultRenderingOptions = null; IModelDescriptor modelDescriptor = viewDescriptor.getModelDescriptor(); if (modelDescriptor instanceof IStringPropertyDescriptor || modelDescriptor instanceof IDatePropertyDescriptor || modelDescriptor instanceof INumberPropertyDescriptor || modelDescriptor instanceof ITimePropertyDescriptor || modelDescriptor instanceof IEnumerationPropertyDescriptor || modelDescriptor instanceof IBooleanPropertyDescriptor || modelDescriptor instanceof IReferencePropertyDescriptor) { asideActions = true; defaultRenderingOptions = ERenderingOptions.ICON; } if (actionMap != null && actionHandler.isAccessGranted(actionMap)) { try { actionHandler.pushToSecurityContext(actionMap); JToolBar toolBar = createViewActionMap(actionMap, view, defaultRenderingOptions, actionHandler, locale); if (asideActions) { viewPanel.add(toolBar, BorderLayout.EAST); } else { viewPanel.add(toolBar, BorderLayout.NORTH); } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } if (secondaryActionMap != null && actionHandler.isAccessGranted(secondaryActionMap)) { try { actionHandler.pushToSecurityContext(secondaryActionMap); JToolBar toolBar = createViewActionMap(secondaryActionMap, view, defaultRenderingOptions, actionHandler, locale); if (asideActions) { viewPanel.add(toolBar, BorderLayout.EAST); } else { viewPanel.add(toolBar, BorderLayout.SOUTH); } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } view.setPeer(viewPanel); } } /** * Creates a view toolbar based on an action map. * * @param actionMap * the action map to create the toolbar for. * @param view * the view to create the toolbar for. * @param defaultRenderingOptions * overrides default rendering options. * @param actionHandler * the action handler used. * @param locale * the locale used. @return the created tool bar. * @return the tool bar */ @SuppressWarnings("ConstantConditions") protected JToolBar createViewActionMap(ActionMap actionMap, IView<JComponent> view, ERenderingOptions defaultRenderingOptions, IActionHandler actionHandler, Locale locale) { JToolBar toolBar = createJToolBar(); ERenderingOptions actionMapRenderingOptions = getDefaultActionMapRenderingOptions(); if (defaultRenderingOptions != null) { actionMapRenderingOptions = defaultRenderingOptions; } if (actionMap.getRenderingOptions() != null) { actionMapRenderingOptions = actionMap.getRenderingOptions(); } boolean defaultHideActionWhenDisabled = getDefaultHideActionWhenDisabled(); if (actionMap.getHideActionWhenDisabled() != null) { defaultHideActionWhenDisabled = actionMap.getHideActionWhenDisabled(); } for (Iterator<ActionList> iter = actionMap.getActionLists(actionHandler).iterator(); iter.hasNext(); ) { ActionList nextActionList = iter.next(); List<JButton> viewActionList = createViewActionList(nextActionList, actionMapRenderingOptions, defaultHideActionWhenDisabled, view, actionHandler, locale); if (viewActionList != null) { for (JButton toolbarButton : viewActionList) { toolBar.add(toolbarButton); } } if (iter.hasNext()) { toolBar.addSeparator(); } } return toolBar; } /** * Create view action list list. * * @param actionList * the action list * @param actionMapRenderingOptions * the toolbar rendering options * @param view * the view * @param actionHandler * the action handler * @param locale * the locale * @return the list */ protected List<JButton> createViewActionList(ActionList actionList, ERenderingOptions actionMapRenderingOptions, boolean defaultHideActionWhenDisabled, IView<JComponent> view, IActionHandler actionHandler, Locale locale) { if (actionHandler.isAccessGranted(actionList)) { List<JButton> viewActionList = new ArrayList<>(); try { actionHandler.pushToSecurityContext(actionList); ERenderingOptions renderingOptions = actionMapRenderingOptions; if (actionList.getRenderingOptions() != null) { renderingOptions = actionList.getRenderingOptions(); } boolean hideActionWhenDisabled = defaultHideActionWhenDisabled; if (actionList.getHideActionWhenDisabled() != null) { hideActionWhenDisabled = actionList.getHideActionWhenDisabled(); } if (actionList.isCollapsable()) { final JButton actionButton; List<IDisplayableAction> actions = new ArrayList<>(); for (IDisplayableAction action : actionList.getActions()) { if (actionHandler.isAccessGranted(action)) { actions.add(action); } } if (!actions.isEmpty()) { if (actions.size() > 1) { actionButton = createJComboButton(); } else { actionButton = createJButton(); } IDisplayableAction mainAction = actions.get(0); Action swingAction = getActionFactory().createAction(mainAction, actionHandler, view, locale); actionButton.setAction(swingAction); switch (renderingOptions) { case ICON: actionButton.setText(""); break; case LABEL: actionButton.setIcon(null); break; default: break; } if (mainAction.getAcceleratorAsString() != null) { KeyStroke ks = KeyStroke.getKeyStroke(mainAction.getAcceleratorAsString()); view.getPeer().getActionMap().put(swingAction.getValue(Action.NAME), swingAction); view.getPeer().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, swingAction.getValue(Action.NAME)); String acceleratorString = KeyEvent.getKeyModifiersText(ks.getModifiers()) + "-" + KeyEvent.getKeyText( ks.getKeyCode()); actionButton.setToolTipText( "<HTML>" + actionButton.getToolTipText() + " <FONT SIZE=\"-2\" COLOR=\"#993366\">" + acceleratorString + "</FONT></HTML>"); } if (actions.size() > 1) { JPopupMenu popupMenu = new JPopupMenu(); for (IDisplayableAction menuAction : actions) { boolean hiddenWhenDisabled = hideActionWhenDisabled; if (menuAction.getHiddenWhenDisabled() != null) { hiddenWhenDisabled = menuAction.getHiddenWhenDisabled(); } final JMenuItem actionItem = createMenuItem(menuAction, view, actionHandler, locale); if (hiddenWhenDisabled) { actionItem.setVisible(actionItem.isEnabled()); actionItem.addPropertyChangeListener("enabled", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { actionItem.setVisible((Boolean) evt.getNewValue()); } }); } switch (renderingOptions) { case ICON: actionItem.setText(""); break; case LABEL: actionItem.setIcon(null); break; default: break; } if (menuAction.getAcceleratorAsString() != null) { KeyStroke ks = KeyStroke.getKeyStroke(menuAction.getAcceleratorAsString()); view.getPeer().getActionMap().put(swingAction.getValue(Action.NAME), swingAction); view.getPeer().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, swingAction.getValue(Action.NAME)); String acceleratorString = KeyEvent.getKeyModifiersText(ks.getModifiers()) + "-" + KeyEvent .getKeyText(ks.getKeyCode()); actionItem.setToolTipText( "<HTML>" + actionItem.getToolTipText() + " <FONT SIZE=\"-2\" COLOR=\"#993366\">" + acceleratorString + "</FONT></HTML>"); } popupMenu.add(actionItem); } ((JComboButton) actionButton).setArrowPopupMenu(popupMenu); } viewActionList.add(actionButton); } } else { for (IDisplayableAction action : actionList.getActions()) { if (actionHandler.isAccessGranted(action)) { boolean hiddenWhenDisabled = hideActionWhenDisabled; if (action.getHiddenWhenDisabled() != null) { hiddenWhenDisabled = action.getHiddenWhenDisabled(); } Action swingAction = getActionFactory().createAction(action, actionHandler, view, locale); final JButton actionButton = createJButton(); actionButton.setAction(swingAction); if (hiddenWhenDisabled) { actionButton.setVisible(actionButton.isEnabled()); actionButton.addPropertyChangeListener("enabled", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { actionButton.setVisible((Boolean) evt.getNewValue()); } }); } if (action.getAcceleratorAsString() != null) { KeyStroke ks = KeyStroke.getKeyStroke(action.getAcceleratorAsString()); view.getPeer().getActionMap().put(swingAction.getValue(Action.NAME), swingAction); view.getPeer().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, swingAction.getValue(Action.NAME)); String acceleratorString = KeyEvent.getKeyModifiersText(ks.getModifiers()) + "-" + KeyEvent.getKeyText( ks.getKeyCode()); actionButton.setToolTipText( "<HTML>" + actionButton.getToolTipText() + " <FONT SIZE=\"-2\" COLOR=\"#993366\">" + acceleratorString + "</FONT></HTML>"); } switch (renderingOptions) { case ICON: actionButton.setText(""); break; case LABEL: actionButton.setIcon(null); break; default: break; } viewActionList.add(actionButton); } } } return viewActionList; } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } return null; } /** * Decorates the created view with the appropriate border. * * @param view * the view to decorate. * @param translationProvider * the translation provider. * @param locale * the locale to use. */ @Override protected void decorateWithBorder(IView<JComponent> view, ITranslationProvider translationProvider, Locale locale) { switch (view.getDescriptor().getBorderType()) { case SIMPLE: view.getPeer().setBorder(BorderFactory.createEtchedBorder()); break; case TITLED: decorateWithTitle(view, translationProvider, locale); break; default: break; } } /** * {@inheritDoc} */ @Override protected void finishComponentConfiguration(IViewDescriptor viewDescriptor, ITranslationProvider translationProvider, Locale locale, IView<JComponent> view) { JComponent viewPeer = view.getPeer(); configureComponent(viewDescriptor, translationProvider, locale, viewPeer); } private void configureComponent(IViewDescriptor viewDescriptor, ITranslationProvider translationProvider, Locale locale, JComponent viewPeer) { if (viewDescriptor.getForeground() != null) { viewPeer.setForeground(createColor(viewDescriptor.getForeground())); } if (viewDescriptor.getBackground() != null) { viewPeer.setBackground(createColor(viewDescriptor.getBackground())); } if (viewDescriptor.getFont() != null && FontHelper.isFontSpec(viewDescriptor.getFont())) { viewPeer.setFont(createFont(viewDescriptor.getFont(), viewPeer.getFont())); } String viewDescription = viewDescriptor.getI18nDescription(translationProvider, locale); viewDescription = completeDescriptionWithLiveDebugUI(viewDescriptor, viewDescription); if (viewDescription != null && viewDescription.length() > 0) { viewPeer.setToolTipText(viewDescription); } } /** * {@inheritDoc} */ @Override protected void showCardInPanel(JComponent cardsPeer, String cardName) { JComponent cardPanel = findFirstCardPanel(cardsPeer); if (cardPanel != null) { ((CardLayout) cardPanel.getLayout()).show(cardPanel, cardName); } } private TableCellRenderer createBooleanTableCellRenderer( @SuppressWarnings("unused") IBooleanPropertyDescriptor propertyDescriptor, @SuppressWarnings("unused") Locale locale) { return new BooleanTableCellRenderer(); } private TableCellRenderer createCollectionTableCellRenderer( @SuppressWarnings("unused") ICollectionPropertyDescriptor<?> propertyDescriptor, @SuppressWarnings("unused") Locale locale) { return null; } static Color createColor(String colorAsHexString) { if (colorAsHexString != null && ColorHelper.isColorSpec(colorAsHexString)) { int[] rgba = ColorHelper.fromHexString(colorAsHexString); return new Color(rgba[0], rgba[1], rgba[2], rgba[3]); } return null; } private TableCellRenderer createColorTableCellRenderer( @SuppressWarnings("unused") IColorPropertyDescriptor propertyDescriptor, @SuppressWarnings("unused") Locale locale) { return new ColorTableCellRenderer(); } private TableCellRenderer createDateTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, IDatePropertyDescriptor propertyDescriptor, TimeZone timeZone, ITranslationProvider translationProvider, Locale locale) { return new FormattedTableCellRenderer( createDateFormatter(propertyViewDescriptor, propertyDescriptor, timeZone, translationProvider, locale)); } private TableCellRenderer createDecimalTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, IDecimalPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { if (propertyDescriptor instanceof IPercentPropertyDescriptor) { return createPercentTableCellRenderer(propertyViewDescriptor, (IPercentPropertyDescriptor) propertyDescriptor, translationProvider, locale); } return new FormattedTableCellRenderer( createDecimalFormatter(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } private TableCellRenderer createDurationTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, IDurationPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormattedTableCellRenderer( createDurationFormatter(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } private TableCellRenderer createEnumerationTableCellRenderer(IEnumerationPropertyDescriptor propertyDescriptor, org.jspresso.framework.util.gui.Dimension iconDimension, ITranslationProvider translationProvider, Locale locale) { return new TranslatedEnumerationTableCellRenderer(propertyDescriptor, iconDimension, translationProvider, locale); } private TableCellRenderer createImageTableCellRenderer(IPropertyDescriptor propertyDescriptor) { return new ImageTableCellRenderer(propertyDescriptor); } static Font createFont(String fontString, Font defaultFont) { org.jspresso.framework.util.gui.Font font = FontHelper.fromString(fontString); int fontStyle; if (font.isBold() && font.isItalic()) { fontStyle = Font.BOLD | Font.ITALIC; } else if (font.isBold()) { fontStyle = Font.BOLD; } else if (font.isItalic()) { fontStyle = Font.ITALIC; } else { fontStyle = Font.PLAIN; } if (font.getName() == null || font.getName().length() == 0) { font.setName(defaultFont.getName()); } if (font.getSize() < 0) { font.setSize(defaultFont.getSize()); } return new Font(font.getName(), fontStyle, font.getSize()); } private GridBagConstraints createGridBagConstraints(CellConstraints viewConstraints) { GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = viewConstraints.getColumn(); constraints.gridy = viewConstraints.getRow(); constraints.gridwidth = viewConstraints.getWidth(); constraints.gridheight = viewConstraints.getHeight(); if (viewConstraints.isWidthResizable()) { constraints.weightx = 1.0D; if (viewConstraints.isHeightResizable()) { constraints.fill = GridBagConstraints.BOTH; } else { constraints.fill = GridBagConstraints.HORIZONTAL; } } if (viewConstraints.isHeightResizable()) { constraints.weighty = 1.0D; if (viewConstraints.isWidthResizable()) { constraints.fill = GridBagConstraints.BOTH; } else { constraints.fill = GridBagConstraints.VERTICAL; } } return constraints; } private TableCellRenderer createIntegerTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, IIntegerPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormattedTableCellRenderer( createIntegerFormatter(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } private JPopupMenu createJPopupMenu(IView<JComponent> view, ActionMap actionMap, IActionHandler actionHandler, Locale locale) { IViewDescriptor viewDescriptor = view.getDescriptor(); JPopupMenu popupMenu = createJPopupMenu(); JLabel titleLabel = new JLabel(); titleLabel.setText(viewDescriptor.getI18nName(actionHandler, locale)); titleLabel.setIcon(getIconFactory().getIcon(viewDescriptor.getIcon(), getIconFactory().getTinyIconSize())); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT); popupMenu.add(titleLabel); popupMenu.addSeparator(); for (Iterator<ActionList> iter = actionMap.getActionLists(actionHandler).iterator(); iter.hasNext(); ) { ActionList nextActionList = iter.next(); if (actionHandler.isAccessGranted(nextActionList)) { try { actionHandler.pushToSecurityContext(nextActionList); for (IDisplayableAction action : nextActionList.getActions()) { if (actionHandler.isAccessGranted(action)) { try { actionHandler.pushToSecurityContext(action); JMenuItem actionItem = createMenuItem(action, view, actionHandler, locale); popupMenu.add(actionItem); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } if (iter.hasNext()) { popupMenu.addSeparator(); } } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } return popupMenu; } private JMenuItem createMenuItem(IDisplayableAction action, IView<JComponent> view, IActionHandler actionHandler, Locale locale) { Action swingAction = getActionFactory().createAction(action, actionHandler, view, locale); JMenuItem actionItem = createJMenuItem(); actionItem.setAction(swingAction); return actionItem; } private TableCellRenderer createNumberTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, INumberPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { TableCellRenderer cellRenderer = null; if (propertyDescriptor instanceof IIntegerPropertyDescriptor) { cellRenderer = createIntegerTableCellRenderer(propertyViewDescriptor, (IIntegerPropertyDescriptor) propertyDescriptor, translationProvider, locale); } else if (propertyDescriptor instanceof IDecimalPropertyDescriptor) { cellRenderer = createDecimalTableCellRenderer(propertyViewDescriptor, (IDecimalPropertyDescriptor) propertyDescriptor, translationProvider, locale); } return cellRenderer; } private TableCellRenderer createPercentTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, IPercentPropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormattedTableCellRenderer( createPercentFormatter(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } private TableCellRenderer createReferenceTableCellRenderer( @SuppressWarnings("unused") IReferencePropertyDescriptor<?> propertyDescriptor, @SuppressWarnings("unused") Locale locale) { return null; } private TableCellRenderer createRelationshipEndTableCellRenderer( IRelationshipEndPropertyDescriptor propertyDescriptor, Locale locale) { TableCellRenderer cellRenderer = null; if (propertyDescriptor instanceof IReferencePropertyDescriptor<?>) { cellRenderer = createReferenceTableCellRenderer((IReferencePropertyDescriptor<?>) propertyDescriptor, locale); } else if (propertyDescriptor instanceof ICollectionPropertyDescriptor<?>) { cellRenderer = createCollectionTableCellRenderer((ICollectionPropertyDescriptor<?>) propertyDescriptor, locale); } return cellRenderer; } private TableCellRenderer createBinaryTableCellRenderer(IBinaryPropertyDescriptor propertyDescriptor, IPropertyViewDescriptor propertyViewDescriptor) { if (propertyDescriptor instanceof IImageBinaryPropertyDescriptor || propertyViewDescriptor instanceof IImageViewDescriptor) { return createImageTableCellRenderer(propertyDescriptor); } return new BinaryTableCellRenderer(propertyDescriptor); } private TableCellRenderer createStringTableCellRenderer(IStringPropertyDescriptor propertyDescriptor, @SuppressWarnings("unused") Locale locale) { if (propertyDescriptor instanceof IPasswordPropertyDescriptor) { return new FormattedTableCellRenderer(new PasswordFormatter()); } if (propertyDescriptor instanceof IImageUrlPropertyDescriptor) { return createImageTableCellRenderer(propertyDescriptor); } return new FormattedTableCellRenderer(null); } private TableCellEditor createTableCellEditor(IView<JComponent> editorView, IActionHandler actionHandler) { SwingViewCellEditorAdapter editor; JComponent peer = editorView.getPeer(); FocusListener[] listeners = peer.getListeners(FocusListener.class); for (FocusListener listener : listeners) { if (listener instanceof FocusGainedListener) { peer.removeFocusListener(listener); } } if (peer instanceof JActionField && ((JActionField) peer).isShowingTextField()) { editor = new SwingViewCellEditorAdapter(editorView, getModelConnectorFactory(), getMvcBinder(), actionHandler) { private static final long serialVersionUID = -1551909997448473681L; @Override public boolean stopCellEditing() { if (((JActionField) getEditorView().getPeer()).isSynchronized()) { fireEditingStopped(); return true; } ((JActionFieldConnector) getEditorView().getConnector()).performActionIfNeeded(); return false; } }; } else { editor = new SwingViewCellEditorAdapter(editorView, getModelConnectorFactory(), getMvcBinder(), actionHandler); } return editor; } private TableCellRenderer createTimeTableCellRenderer(IPropertyViewDescriptor propertyViewDescriptor, ITimePropertyDescriptor propertyDescriptor, ITranslationProvider translationProvider, Locale locale) { return new FormattedTableCellRenderer( createTimeFormatter(propertyViewDescriptor, propertyDescriptor, translationProvider, locale)); } private void decorateWithTitle(IView<JComponent> view, ITranslationProvider translationProvider, Locale locale) { view.getPeer().setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), view.getDescriptor().getI18nName(translationProvider, locale))); } private void expandAll(final JTree tree, final TreePath tp) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (tp == null) { return; } Object node = tp.getLastPathComponent(); TreeModel model = tree.getModel(); if (!model.isLeaf(node)) { tree.expandPath(tp); for (int i = 0; i < model.getChildCount(node); i++) { expandAll(tree, tp.pathByAddingChild(model.getChild(node, i))); } } } }); } private List<String> getDescriptorPathFromConnectorTreePath(TreePath connectorTreePath) { List<String> descriptorPath = new ArrayList<>(); if (connectorTreePath != null) { Object[] connectors = connectorTreePath.getPath(); for (Object connector : connectors) { if (connector instanceof ICollectionConnectorProvider) { descriptorPath.add(((IValueConnector) connector).getId()); } } } return descriptorPath; } private int getSelectionMode(ICollectionViewDescriptor viewDescriptor) { int selectionMode; switch (viewDescriptor.getSelectionMode()) { case SINGLE_SELECTION: case SINGLE_CUMULATIVE_SELECTION: selectionMode = ListSelectionModel.SINGLE_SELECTION; break; case SINGLE_INTERVAL_SELECTION: case SINGLE_INTERVAL_CUMULATIVE_SELECTION: selectionMode = ListSelectionModel.SINGLE_INTERVAL_SELECTION; break; case MULTIPLE_INTERVAL_SELECTION: case MULTIPLE_INTERVAL_CUMULATIVE_SELECTION: default: selectionMode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION; break; } return selectionMode; } private void showJTablePopupMenu(JTable table, IView<JComponent> tableView, MouseEvent evt, IActionHandler actionHandler, Locale locale) { int row = table.rowAtPoint(evt.getPoint()); if (row < 0) { return; } if (!table.isRowSelected(row)) { table.setRowSelectionInterval(row, row); } ActionMap actionMap = tableView.getDescriptor().getActionMap(); if (actionMap != null && actionHandler.isAccessGranted(actionMap)) { try { actionHandler.pushToSecurityContext(actionMap); JPopupMenu popupMenu = createJPopupMenu(tableView, actionMap, actionHandler, locale); popupMenu.show(table, evt.getX(), evt.getY()); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } private void showJTreePopupMenu(JTree tree, IView<JComponent> treeView, MouseEvent evt, IActionHandler actionHandler, Locale locale) { TreePath path = tree.getPathForLocation(evt.getX(), evt.getY()); if (path == null) { return; } if (!tree.isPathSelected(path)) { tree.setSelectionPath(path); } if (path.getLastPathComponent() instanceof ICollectionConnector) { TreePath[] allNodePaths = new TreePath[((ICollectionConnector) path.getLastPathComponent()) .getChildConnectorCount()]; for (int i = 0; i < allNodePaths.length; i++) { allNodePaths[i] = path.pathByAddingChild( ((ICollectionConnector) path.getLastPathComponent()).getChildConnector(i)); } tree.addSelectionPaths(allNodePaths); } IValueConnector viewConnector = (IValueConnector) path.getLastPathComponent(); ActionMap actionMap; IViewDescriptor viewDescriptor; if (viewConnector == tree.getModel().getRoot()) { viewDescriptor = treeView.getDescriptor(); } else { viewDescriptor = TreeDescriptorHelper.getSubtreeDescriptorFromPath( ((ITreeViewDescriptor) treeView.getDescriptor()).getRootSubtreeDescriptor(), getDescriptorPathFromConnectorTreePath(path)).getNodeGroupDescriptor(); if (!(viewConnector instanceof ICollectionConnector)) { viewConnector = viewConnector.getParentConnector(); } } actionMap = viewDescriptor.getActionMap(); if (actionMap != null && actionHandler.isAccessGranted(actionMap)) { try { actionHandler.pushToSecurityContext(actionMap); BasicView<JComponent> treeLevelView = new BasicView<JComponent>(tree); treeLevelView.setConnector(viewConnector); treeLevelView.setDescriptor(viewDescriptor); JPopupMenu popupMenu = createJPopupMenu(treeLevelView, actionMap, actionHandler, locale); popupMenu.show(tree, evt.getX(), evt.getY()); } finally { actionHandler.restoreLastSecurityContextSnapshot(); } } } private void showPopupMenu(JComponent sourceComponent, IView<JComponent> view, MouseEvent evt, IActionHandler actionHandler, Locale locale) { if (sourceComponent instanceof JTree) { showJTreePopupMenu((JTree) sourceComponent, view, evt, actionHandler, locale); } else if (sourceComponent instanceof JTable) { showJTablePopupMenu((JTable) sourceComponent, view, evt, actionHandler, locale); } } private final class ColorTableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 6014260077437906330L; /** * {@inheritDoc} */ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value != null) { int[] rgba = ColorHelper.fromHexString((String) value); setBackground(new Color(rgba[0], rgba[1], rgba[2], rgba[3])); } else { setBackground(null); } return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } } private final class ConnectorTreeCellRenderer extends DefaultTreeCellRenderer { private static final long serialVersionUID = -5153268751092971328L; private final boolean displayIcon; public ConnectorTreeCellRenderer(boolean displayIcon) { this.displayIcon = displayIcon; } /** * {@inheritDoc} */ @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean nodeHasFocus) { JLabel renderer = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, nodeHasFocus); if (value instanceof IValueConnector) { if (value instanceof IRenderableCompositeValueConnector) { renderer.setText(((IRenderableCompositeValueConnector) value).getDisplayValue()); if (displayIcon) { renderer.setIcon(getIconFactory().getIcon(((IRenderableCompositeValueConnector) value).getDisplayIcon(), getIconFactory().getSmallIconSize())); } String displayDescription = ((IRenderableCompositeValueConnector) value).getDisplayDescription(); if (displayDescription != null && displayDescription.length() > 0) { ToolTipManager.sharedInstance().registerComponent(tree); renderer.setToolTipText(displayDescription); } } else { renderer.setText(value.toString()); } } return renderer; } } private final class PopupListener extends MouseAdapter { private final IActionHandler actionHandler; private final Locale locale; private final JComponent sourceComponent; private final IView<JComponent> view; /** * Constructs a new {@code PopupListener} instance. * * @param sourceComponent * the source component. * @param view * the view. * @param actionHandler * the action handler. * @param locale * the locale. */ public PopupListener(JComponent sourceComponent, IView<JComponent> view, IActionHandler actionHandler, Locale locale) { this.sourceComponent = sourceComponent; this.view = view; this.actionHandler = actionHandler; this.locale = locale; } /** * {@inheritDoc} */ @Override public void mousePressed(MouseEvent evt) { maybeShowPopup(evt); } /** * {@inheritDoc} */ @Override public void mouseReleased(MouseEvent evt) { maybeShowPopup(evt); } private void maybeShowPopup(MouseEvent evt) { if (evt.isPopupTrigger()) { showPopupMenu(sourceComponent, view, evt, actionHandler, locale); } } } private final class TranslatedEnumerationListCellRenderer extends DefaultListCellRenderer { private static final long serialVersionUID = -5694559709701757582L; private final ITranslationProvider translationProvider; private final Locale locale; private final IEnumerationPropertyDescriptor propertyDescriptor; private final org.jspresso.framework.util.gui.Dimension iconDimension; /** * Constructs a new {@code TranslatedEnumerationCellRenderer} instance. * * @param propertyDescriptor * the property descriptor from which the enumeration name is * taken. The prefix used to lookup translation keys in the form * keyPrefix.value is the propertyDescriptor enumeration name. * @param iconDimension * the icon dimension * @param translationProvider * the translation provider. * @param locale * the locale to lookup the translation. */ public TranslatedEnumerationListCellRenderer(IEnumerationPropertyDescriptor propertyDescriptor, org.jspresso.framework.util.gui.Dimension iconDimension, ITranslationProvider translationProvider, Locale locale) { this.propertyDescriptor = propertyDescriptor; this.iconDimension = iconDimension; this.translationProvider = translationProvider; this.locale = locale; } /** * {@inheritDoc} */ @Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); label.setIcon(getIconFactory().getIcon(propertyDescriptor.getIconImageURL(String.valueOf(value)), iconDimension)); if (value != null && propertyDescriptor.isTranslated()) { label.setText(propertyDescriptor.getI18nValue((String) value, translationProvider, locale)); } else { if (value == null) { label.setText(" "); } else { label.setText(String.valueOf(value)); } } return label; } } private final class TranslatedEnumerationTableCellRenderer extends EvenOddTableCellRenderer { private static final long serialVersionUID = -4500472602998482756L; private final ITranslationProvider translationProvider; private final Locale locale; private final IEnumerationPropertyDescriptor propertyDescriptor; private final org.jspresso.framework.util.gui.Dimension iconDimension; /** * Constructs a new {@code TranslatedEnumerationTableCellRenderer} * instance. * * @param propertyDescriptor * the property descriptor from which the enumeration name is * taken. The prefix used to lookup translation keys in the form * keyPrefix.value is the propertyDescriptor enumeration name. * @param iconDimension * the icon dimension * @param translationProvider * the translation provider. * @param locale * the locale to lookup the translation. */ public TranslatedEnumerationTableCellRenderer(IEnumerationPropertyDescriptor propertyDescriptor, org.jspresso.framework.util.gui.Dimension iconDimension, ITranslationProvider translationProvider, Locale locale) { super(); this.propertyDescriptor = propertyDescriptor; this.iconDimension = iconDimension; this.translationProvider = translationProvider; this.locale = locale; } /** * {@inheritDoc} */ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setIcon(getIconFactory().getIcon(propertyDescriptor.getIconImageURL(String.valueOf(value)), iconDimension)); return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } /** * {@inheritDoc} */ @Override protected void setValue(Object value) { if (value instanceof IValueConnector) { Object connectorValue = ((IValueConnector) value).getConnectorValue(); if (connectorValue != null && propertyDescriptor.isTranslated()) { super.setValue(propertyDescriptor.getI18nValue((String) connectorValue, translationProvider, locale)); } else { if (connectorValue == null) { super.setValue(""); } else { super.setValue(String.valueOf(connectorValue)); } } } else { if (value != null && propertyDescriptor.isTranslated()) { super.setValue(propertyDescriptor.getI18nValue((String) value, translationProvider, locale)); } else { if (value == null) { super.setValue(""); } else { super.setValue(String.valueOf(value)); } } } } } private final class ImageTableCellRenderer extends EvenOddTableCellRenderer { private static final long serialVersionUID = 9155173076041284128L; @SuppressWarnings("unused") private final IPropertyDescriptor propertyDescriptor; /** * Constructs a new {@code ImageTableCellRenderer} instance. * * @param propertyDescriptor * the image property descriptor (either image url or image * binary). */ public ImageTableCellRenderer(IPropertyDescriptor propertyDescriptor) { this.propertyDescriptor = propertyDescriptor; setHorizontalAlignment(SwingConstants.CENTER); setVerticalAlignment(SwingConstants.CENTER); } /** * {@inheritDoc} */ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value instanceof byte[]) { setIcon(new ImageIcon((byte[]) value)); } else if (value instanceof String) { setIcon(new ImageIcon(UrlHelper.createURL((String) value))); } else { setIcon(null); } return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } /** * {@inheritDoc} */ @Override protected void setValue(Object value) { // No string rendering } } private final class BinaryTableCellRenderer extends BooleanTableCellRenderer { private static final long serialVersionUID = 9155173076041284128L; @SuppressWarnings("unused") private final IPropertyDescriptor propertyDescriptor; /** * Constructs a new {@code BinaryTableCellRenderer} instance. * * @param propertyDescriptor * the binary property descriptor. */ public BinaryTableCellRenderer(IPropertyDescriptor propertyDescriptor) { this.propertyDescriptor = propertyDescriptor; } /** * {@inheritDoc} */ @Override protected void setValue(Object value) { if (value != null) { setSelected(true); } else { setSelected(false); } } } private void configureHorizontalAlignment(JTextField textField, EHorizontalAlignment horizontalAlignment) { switch (horizontalAlignment) { case LEFT: textField.setHorizontalAlignment(SwingConstants.LEFT); break; case CENTER: textField.setHorizontalAlignment(SwingConstants.CENTER); break; case RIGHT: textField.setHorizontalAlignment(SwingConstants.RIGHT); break; default: break; } } private void configureHorizontalAlignment(JLabel label, EHorizontalAlignment horizontalAlignment) { switch (horizontalAlignment) { case LEFT: label.setHorizontalAlignment(SwingConstants.LEFT); break; case CENTER: label.setHorizontalAlignment(SwingConstants.CENTER); break; case RIGHT: label.setHorizontalAlignment(SwingConstants.RIGHT); break; default: break; } } /** * {@inheritDoc} */ @Override protected IView<JComponent> createPropertyView(final IPropertyViewDescriptor propertyViewDescriptor, final IActionHandler actionHandler, Locale locale) { final IView<JComponent> propertyView = super.createPropertyView(propertyViewDescriptor, actionHandler, locale); final JComponent peer = propertyView.getPeer(); if (peer instanceof JLabel) { configureHorizontalAlignment((JLabel) peer, propertyViewDescriptor.getHorizontalAlignment()); } else if (peer instanceof JTextField) { configureHorizontalAlignment((JTextField) peer, propertyViewDescriptor.getHorizontalAlignment()); } if (propertyViewDescriptor.getFocusGainedAction() != null) { peer.addFocusListener( new FocusGainedListener(actionHandler, propertyView, propertyViewDescriptor.getFocusGainedAction())); } return propertyView; } /** * Finds the first focusable component in the hierarchy. * * @param root * th hierarchy root to explore. * @return the first focusable component or null if none. */ protected JComponent findFirstFocusableComponent(Component root) { if (root instanceof JTextComponent || root instanceof JCheckBox || root instanceof JComboBox || root instanceof JDateField || root instanceof JTable) { return (JComponent) root; } if (root instanceof Container) { for (Component child : ((Container) root).getComponents()) { JComponent focusableChild = findFirstFocusableComponent(child); if (focusableChild != null) { return focusableChild; } } } return null; } /** * Finds the first editable component in the hierarchy. * * @param root * th hierarchy root to explore. * @return the first editable component or null if none. */ protected JComponent findFirstEditableComponent(Component root) { if (root instanceof JTable) { return (JComponent) root; } if (root instanceof Container) { for (Component child : ((Container) root).getComponents()) { JComponent editableChild = findFirstEditableComponent(child); if (editableChild != null) { return editableChild; } } } return null; } /** * {@inheritDoc} */ @Override public void focus(JComponent component) { final JComponent focusableChild = findFirstFocusableComponent(component); if (focusableChild != null) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { focusableChild.requestFocusInWindow(); } }); } } /** * {@inheritDoc} */ @Override public void edit(JComponent component) { JComponent editableChild = findFirstEditableComponent(component); if (editableChild instanceof JTable) { JTable table = (JTable) editableChild; if (table.getSelectedRow() >= 0) { table.editCellAt(table.getSelectedRow(), 0); Component editor = table.getEditorComponent(); if (editor instanceof JComponent) { focus((JComponent) editor); } } } } /** * Configures a property view action by initializing its static context. * * @param propertyViewDescriptor * the property view descriptor the action is attached to. * @param propertyViewAction * the action to configure. */ protected void configurePropertyViewAction(IPropertyViewDescriptor propertyViewDescriptor, Action propertyViewAction) { Map<String, Object> staticContext = new HashMap<>(); staticContext.put(ActionContextConstants.PROPERTY_VIEW_DESCRIPTOR, propertyViewDescriptor); propertyViewAction.putValue(IAction.STATIC_CONTEXT_KEY, staticContext); } /** * Attach char action. * * @param view * the view * @param viewComponent * the view component * @param action * the action * @param actionHandler * the action handler * @param locale * the locale */ protected void attachCharAction(final IView<JComponent> view, final JTextComponent viewComponent, final IDisplayableAction action, final IActionHandler actionHandler, Locale locale) { if (action != null) { viewComponent.addKeyListener(new KeyAdapter() { private void triggerCharAction() { String text = viewComponent.getText(); Map<String, Object> context = getActionFactory().createActionContext(actionHandler, view, view.getConnector(), null, view.getPeer()); context.put(ActionContextConstants.ACTION_COMMAND, text); actionHandler.execute(action, context); } @Override public void keyTyped(KeyEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { triggerCharAction(); } }); } }); } } private class FocusGainedListener extends FocusAdapter { private IActionHandler actionHandler; private IView<JComponent> view; private IAction action; public FocusGainedListener(IActionHandler actionHandler, IView<JComponent> view, IAction action) { this.actionHandler = actionHandler; this.view = view; this.action = action; } @Override public void focusGained(FocusEvent e) { Map<String, Object> context = getActionFactory().createActionContext(actionHandler, view, view.getConnector(), null, view.getPeer()); actionHandler.execute(action, context); } } }