Dépôt officiel du code source de l'ERP OpenConcerto
Rev 174 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.sql.element;
import org.openconcerto.sql.Log;
import org.openconcerto.sql.PropsConfiguration;
import org.openconcerto.sql.model.FieldMapper;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLType;
import org.openconcerto.sql.request.RowItemDesc;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.sql.users.rights.UserRightsManager;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.JDate;
import org.openconcerto.ui.JLabelBold;
import org.openconcerto.ui.component.ITextArea;
import org.openconcerto.ui.group.Group;
import org.openconcerto.ui.group.Item;
import org.openconcerto.ui.group.LayoutHints;
import org.openconcerto.utils.i18n.TranslationManager;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class GroupSQLComponent extends BaseSQLComponent {
public static final String ITEM_RIGHT_CODE = "GROUP_ITEM_SHOW";
private final Group group;
private final int columns = 2;
private final Map<String, JComponent> labels = new HashMap<>();
private final Map<String, JComponent> editors = new HashMap<>();
private String startTabAfter = null;
private boolean tabGroup;
private int tabDepth;
private JTabbedPane pane;
private final List<String> tabsGroupIDs = new ArrayList<String>();
private Group additionnalFieldsGroup;
private final boolean hasAdditionnalFields;
public GroupSQLComponent(final SQLElement element) {
this(element, element.getDefaultGroup());
}
public GroupSQLComponent(final SQLElement element, final Group group) {
super(element);
if (element == null) {
throw new IllegalArgumentException("null SQLElement");
}
if (group == null) {
throw new IllegalArgumentException("null group (SQLElement : " + element + ")");
}
this.group = group;
this.hasAdditionnalFields = this.getElement().getAdditionalFields().size() > 0;
this.additionnalFieldsGroup = getAdditionalFieldsGroup(group.getDescendantGroups());
}
private Group getAdditionalFieldsGroup(Collection<Group> items) {
for (Group g : items) {
if (g.getId().endsWith("additionalElementFields")) {
return g;
}
}
return null;
}
protected final Group getGroup() {
return this.group;
}
public void startTabGroupAfter(String id) {
this.startTabAfter = id;
}
@Override
protected void addViews() {
this.setLayout(new GridBagLayout());
final GridBagConstraints c = new DefaultGridBagConstraints();
c.fill = GridBagConstraints.NONE;
this.tabGroup = false;
this.tabDepth = 0;
// On laisse la place en haut pour les additionnals fields
if (this.hasAdditionnalFields) {
c.gridy = this.getElement().getAdditionalFields().size() / 2 + 1;
}
layout(this.group, 0, 0, 0, c, this);
}
public void layout(final Item currentItem, final Integer order, int x, final int level, GridBagConstraints c, JPanel panel) {
final String id = currentItem.getId();
final LayoutHints size = currentItem.getLocalHint();
if (!size.isVisible()) {
return;
}
if (size.isSeparated() || size.isSplit()) {
x = 0;
c.gridx = 0;
c.gridy++;
}
if (currentItem instanceof Group) {
final Group currentGroup = (Group) currentItem;
final int stop = currentGroup.getSize();
c.weighty = 0;
if (this.tabGroup && level == this.tabDepth) {
panel = new JPanel();
panel.setLayout(new GridBagLayout());
panel.setOpaque(false);
c = new DefaultGridBagConstraints();
x = 0;
c.fill = GridBagConstraints.NONE;
String label = TranslationManager.getInstance().getTranslationForItem(id);// getRIVDescForId(id).getLabel();
if (label == null) {
label = id;
}
this.pane.addTab(label, panel);
this.tabsGroupIDs.add(currentGroup.getId());
} else {
if (size.showLabel() && getLabel(id) != null) {
x = 0;
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.weightx = 1;
c.gridwidth = 4;
JComponent comp = getLabel(id);
panel.add(comp, c);
c.gridy++;
}
}
if (this.hasAdditionnalFields) {
if ((currentGroup == this.group && this.additionnalFieldsGroup == null) || (currentGroup == this.additionnalFieldsGroup)) {
for (String field : this.getElement().getAdditionalFields().keySet()) {
Item item = new Item(field, new LayoutHints(false, false, true, false, true, false));
int fill = c.fill;
double weightx = c.weightx;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
layout(item, 100, x, level + 1, c, panel);
c.weightx = weightx;
c.fill = fill;
}
}
}
for (int i = 0; i < stop; i++) {
final Item subGroup = currentGroup.getItem(i);
final Integer subGroupOrder = currentGroup.getOrder(i);
layout(subGroup, subGroupOrder, x, level + 1, c, panel);
}
if (this.tabGroup && level == this.tabDepth) {
JPanel spacer = new JPanel();
spacer.setOpaque(false);
c.gridy++;
c.weighty = 0.0001;
panel.add(spacer, c);
}
} else {
c.gridwidth = 1;
if (size.showLabel()) {
c.weightx = 0;
c.weighty = 0;
// Label
if (size.isSplit()) {
c.gridwidth = 4;
c.weightx = 1;
c.fill = GridBagConstraints.NONE;
} else {
c.fill = GridBagConstraints.HORIZONTAL;
}
panel.add(getLabel(id), c);
if (size.isSplit()) {
c.gridy++;
c.gridx = 0;
} else {
c.gridx++;
}
}
// Editor
final JComponent editor = getEditor(id);
if (size.fillWidth() && size.fillHeight()) {
c.fill = GridBagConstraints.BOTH;
} else if (size.fillWidth()) {
c.fill = GridBagConstraints.HORIZONTAL;
} else if (size.fillHeight()) {
c.fill = GridBagConstraints.VERTICAL;
} else {
c.fill = GridBagConstraints.NONE;
DefaultGridBagConstraints.lockMinimumSize(editor);
}
if (size.fillHeight()) {
c.weighty = 1;
} else {
c.weighty = 0;
}
if (size.largeWidth()) {
if (size.isSplit() || !size.showLabel()) {
c.gridwidth = this.columns * 2;
} else {
c.gridwidth = this.columns * 2 - 1;
}
} else {
if (size.showLabel() && !size.isSplit()) {
c.gridwidth = 1;
} else {
c.gridwidth = 2;
}
}
if (c.gridx % 2 == 1) {
c.weightx = 1;
}
panel.add(editor, c);
try {
JComponent comp = editor;
if (editor instanceof JScrollPane) {
JScrollPane pane = (JScrollPane) editor;
comp = (JComponent) pane.getViewport().getView();
}
this.addView(comp, id);
// avoid collapsing of Mode de réglement in client
if (comp instanceof ElementSQLObject)
DefaultGridBagConstraints.lockMinimumSize(editor);
} catch (final Exception e) {
Log.get().warning(e.getMessage());
}
if (size.largeWidth()) {
if (size.isSplit()) {
c.gridx += 4;
} else {
c.gridx += 3;
}
} else {
c.gridx++;
}
if (c.gridx >= this.columns * 2 || size.isSeparated()) {
c.gridx = 0;
c.gridy++;
x = 0;
}
}
if (id.equals(this.startTabAfter)) {
if (this.tabGroup) {
throw new IllegalArgumentException("ID " + id + " already set as tab");
}
this.tabGroup = true;
this.tabDepth = level;
this.pane = new JTabbedPane();
c.gridx = 0;
c.gridy++;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = 4;
panel.add(this.pane, c);
}
}
public final void setTabEnabledAt(final String groupID, final boolean enabled) {
this.pane.setEnabledAt(this.tabsGroupIDs.indexOf(groupID), enabled);
}
public final boolean isTabEnabledAt(final String groupID) {
return this.pane.isEnabledAt(this.tabsGroupIDs.indexOf(groupID));
}
public final void selectTabEnabled() {
final int index = this.pane.getSelectedIndex();
if (!this.pane.isEnabledAt(index)) {
final int count = this.pane.getTabCount();
// 1 since index is disabled
for (int i = 1; i < count; i++) {
final int mod = (index + i) % count;
if (this.pane.isEnabledAt(mod)) {
this.pane.setSelectedIndex(mod);
return;
}
}
}
}
@Override
public Component addView(JComponent comp, String id) {
final FieldMapper fieldMapper = PropsConfiguration.getInstance().getFieldMapper();
SQLField field = null;
if (fieldMapper != null) {
field = fieldMapper.getSQLFieldForItem(id);
}
// Maybe the id is a field name (deprecated)
if (field == null) {
field = this.getTable().getFieldRaw(id);
}
// allow to add components in the UI which aren't in the request
if (field != null)
return super.addView(comp, field.getName());
else
return comp;
}
public JComponent createEditor(final String id) {
if (GlobalMapper.getInstance().get(id + ".editor") != null) {
try {
final Class<?> cl = (Class<?>) GlobalMapper.getInstance().get(id + ".editor");
return (JComponent) cl.newInstance();
} catch (final Exception e) {
e.printStackTrace();
}
}
if (id.startsWith("(") && id.endsWith(")*")) {
try {
final String table = id.substring(1, id.length() - 2).trim();
final String idEditor = GlobalMapper.getInstance().getIds(table).get(0) + ".editor";
final Class<?> cl = (Class<?>) GlobalMapper.getInstance().get(idEditor);
return (JComponent) cl.newInstance();
} catch (final Exception e) {
e.printStackTrace();
}
}
final FieldMapper fieldMapper = PropsConfiguration.getInstance().getFieldMapper();
SQLField field = null;
if (fieldMapper != null) {
field = fieldMapper.getSQLFieldForItem(id);
}
// Maybe the id is a field name (deprecated)
if (field == null) {
field = this.getTable().getFieldRaw(id);
}
if (field == null) {
final JLabel jLabel = new JLabelBold("No field " + id);
jLabel.setForeground(Color.RED.darker());
String t = "<html>";
final Set<SQLField> fields = this.getTable().getFields();
for (final SQLField sqlField : fields) {
t += sqlField.getFullName() + "<br>";
}
t += "</html>";
jLabel.setToolTipText(t);
return jLabel;
}
final SQLType type = field.getType();
final JComponent comp;
if (getElement().getPrivateElement(field.getName()) != null) {
// private
final SQLComponent sqlcomp = this.getElement().getPrivateElement(field.getName()).createDefaultComponent();
final DefaultElementSQLObject dobj = new DefaultElementSQLObject(this, sqlcomp);
dobj.setDecorated(false);
dobj.showSeparator(false);
DefaultGridBagConstraints.lockMinimumSize(sqlcomp);
comp = dobj;
} else if (field.isKey()) {
// foreign
final SQLElement foreignElement = getElement().getForeignElement(field.getName());
if (foreignElement == null) {
comp = new JLabelBold("no element for foreignd " + id);
comp.setForeground(Color.RED.darker());
Log.get().severe("no element for foreign " + field.getName());
} else {
comp = new ElementComboBox();
((ElementComboBox) comp).init(foreignElement);
}
comp.setOpaque(false);
} else {
if (Boolean.class.isAssignableFrom(type.getJavaType())) {
// TODO hack to view the focus (should try to paint around the button)
comp = new JCheckBox(" ");
comp.setOpaque(false);
} else if (Date.class.isAssignableFrom(type.getJavaType())) {
comp = new JDate();
comp.setOpaque(false);
} else if (String.class.isAssignableFrom(type.getJavaType()) && type.getSize() >= 500) {
comp = new ITextArea();
} else {
comp = new JTextField(Math.min(30, type.getSize()));
}
}
return comp;
}
protected JComponent createLabel(final String id) {
final JLabel jLabel = new JLabel();
jLabel.setHorizontalAlignment(SwingConstants.RIGHT);
return jLabel;
}
private void registerPopupMenu(final JComponent label, final String id) {
label.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON3 && e.getModifiersEx() == 128) {
final JPopupMenu popMenu = new JPopupMenu();
final JMenu menuItemInfo = new JMenu("Information");
menuItemInfo.add(new JMenuItem("id: " + id));
menuItemInfo.add(new JMenuItem("label: " + getLabel(id).getClass().getName() + ":" + getLabel(id)));
menuItemInfo.add(new JMenuItem("editor: " + getEditor(id).getClass().getName() + ":" + getEditor(id)));
popMenu.add(menuItemInfo);
final JMenuItem menuItemDoc = new JMenuItem("Modifier la documentation");
menuItemDoc.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
new DocumentationEditorFrame(GroupSQLComponent.this, id).setVisible(true);
}
});
popMenu.add(menuItemDoc);
popMenu.show(label, e.getX(), e.getY());
}
}
});
}
@Override
protected void updateUI(String id, RowItemDesc desc) {
super.updateUI(id, desc);
updateUI(id, getLabel(id), desc, Color.RED.darker());
}
public JComponent getLabel(final String id) {
JComponent label = this.labels.get(id);
if (label == null) {
label = createLabel(id);
if (!UserRightsManager.getCurrentUserRights().haveRight(ITEM_RIGHT_CODE, id)
|| !UserRightsManager.getCurrentUserRights().haveRight(ITEM_RIGHT_CODE, getElement().getTable().getName() + "." + id)) {
label.setVisible(false);
}
this.labels.put(id, label);
registerPopupMenu(label, id);
final RowItemDesc rivDesc = getRIVDescForId(id);
updateUI(id, rivDesc);
}
return label;
}
public RowItemDesc getRIVDescForId(final String id) {
if (TranslationManager.getInstance().getLocale() != null) {
final String t = TranslationManager.getInstance().getTranslationForItem(id);
if (t != null) {
return new RowItemDesc(t, t);
}
}
String fieldName = null;
final FieldMapper fieldMapper = PropsConfiguration.getInstance().getFieldMapper();
if (fieldMapper != null) {
final SQLField sqlFieldForItem = fieldMapper.getSQLFieldForItem(id);
if (sqlFieldForItem != null) {
fieldName = sqlFieldForItem.getName();
}
}
if (fieldName == null) {
fieldName = id;
}
final RowItemDesc rivDesc = getRIVDesc(fieldName);
return rivDesc;
}
public JComponent getEditor(final String id) {
JComponent editor = this.editors.get(id);
if (editor == null) {
editor = createEditor(id);
if (!UserRightsManager.getCurrentUserRights().haveRight(ITEM_RIGHT_CODE, id)
|| !UserRightsManager.getCurrentUserRights().haveRight(ITEM_RIGHT_CODE, getElement().getTable().getName() + "." + id)) {
editor.setVisible(false);
}
this.editors.put(id, editor);
}
return editor;
}
}