/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.smart.dataui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.CellEditor;
import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.IScriptExecuter;
import com.servoy.j2db.component.ComponentFactory;
import com.servoy.j2db.component.ISupportAsyncLoading;
import com.servoy.j2db.dataprocessing.DataAdapterList;
import com.servoy.j2db.dataprocessing.FoundSet;
import com.servoy.j2db.dataprocessing.FoundSetManager;
import com.servoy.j2db.dataprocessing.IDisplay;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.dataprocessing.IRecordInternal;
import com.servoy.j2db.dataprocessing.ISwingFoundSet;
import com.servoy.j2db.dataprocessing.PrototypeState;
import com.servoy.j2db.dataprocessing.SortColumn;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.IPersist;
import com.servoy.j2db.persistence.Portal;
import com.servoy.j2db.persistence.Relation;
import com.servoy.j2db.persistence.RepositoryException;
import com.servoy.j2db.printing.ISupportXMLOutput;
import com.servoy.j2db.printing.XMLPrintHelper;
import com.servoy.j2db.scripting.IScriptable;
import com.servoy.j2db.scripting.IScriptableProvider;
import com.servoy.j2db.smart.TableView;
import com.servoy.j2db.ui.DataRendererOnRenderWrapper;
import com.servoy.j2db.ui.IDataRenderer;
import com.servoy.j2db.ui.IPortalComponent;
import com.servoy.j2db.ui.IScrollPane;
import com.servoy.j2db.ui.ISupportOnRenderCallback;
import com.servoy.j2db.ui.ISupportOnRenderWrapper;
import com.servoy.j2db.ui.ISupportRowStyling;
import com.servoy.j2db.ui.runtime.IRuntimeComponent;
import com.servoy.j2db.ui.scripting.RuntimePortal;
import com.servoy.j2db.util.ComponentFactoryHelper;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.EnableScrollPanel;
import com.servoy.j2db.util.IDestroyable;
import com.servoy.j2db.util.IFocusCycleRoot;
import com.servoy.j2db.util.ISkinnable;
import com.servoy.j2db.util.IStyleRule;
import com.servoy.j2db.util.IStyleSheet;
import com.servoy.j2db.util.ISupportFocusTransfer;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.editlist.AbstractEditListModel;
import com.servoy.j2db.util.editlist.JEditList;
import com.servoy.j2db.util.gui.AutoTransferFocusListener;
/**
* Runtime swing portal component
* @author jblok
*/
public class PortalComponent extends EnableScrollPanel implements ListSelectionListener, ISkinnable, IScrollPane, TableModelListener, ISupportXMLOutput,
IPortalComponent, IFocusCycleRoot<Component>, ISupportFocusTransfer
{
private static final long serialVersionUID = 1L;
private static final String ACTION_GO_OUT_TO_NEXT = "goOutToNext";
private static final String ACTION_GO_OUT_TO_PREV = "goOutToPrev";
private final DefaultListSelectionModel EMPTY_SELECTION = new DefaultListSelectionModel();
private final DefaultTableModel EMPTY_DATA = new DefaultTableModel();
private TableView table;
private Component[] editorComponents;
private Component[] rendererComponents;
private PortalMultilineList list;
private DataRenderer renderer;
private DataRenderer editor;
private final IApplication application;
private DataAdapterList dal;
private String relationName;
private List<SortColumn> defaultSort = null;
private boolean transferFocusBackwards = false;
private final RuntimePortal scriptable;
public PortalComponent(final IApplication app, RuntimePortal scriptable, Form form, Portal meta, IScriptExecuter el, boolean printing)
{
application = app;
setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, new JPanel());
ComponentFactory.applyScrollBarsProperty(this, meta);
if (meta.getMultiLine())
{
list = new PortalMultilineList(meta, el);
try
{
renderer = (DataRenderer)application.getDataRenderFactory().createPortalRenderer(app, meta, (Form)meta.getParent(), el, printing, null);
renderer.setRowBGColorProvider(meta.getRowBGColorCalculation(), meta.getInstanceMethodArguments("rowBGColorCalculation"));
editor = (DataRenderer)application.getDataRenderFactory().createPortalRenderer(app, meta, (Form)meta.getParent(), el, printing, null);
FormBodyEditor formEditor = new FormBodyEditor(editor);
dal = editor.getDataAdapterList();
list.setPrototypeCellValue(new PrototypeState(null));//this call is extremely important, it prevent all rows retrieval
list.setCellRenderer(renderer);
list.setCellEditor(formEditor);
java.awt.Color bg = meta.getBackground();
if (bg != null) list.setBackground(bg);
Component[] rendererComponents = renderer.getComponents();
for (Component element : rendererComponents)
{
if (element instanceof ISupportAsyncLoading)
{
//in list it is impossible to get lazy loaded images displaying correctly, due to needed repaintfire, which we cannot initiate
((ISupportAsyncLoading)element).setAsyncLoadingEnabled(false);
}
}
Iterator<IPersist> portalObjectsIte = meta.getAllObjects();
IPersist portalObj;
while (portalObjectsIte.hasNext())
{
portalObj = portalObjectsIte.next();
addOnRender(renderer.getFieldComponents().get(portalObj), meta, portalObj, el);
addOnRender(editor.getFieldComponents().get(portalObj), meta, portalObj, el);
}
}
catch (Exception ex)
{
Debug.error(ex);
}
list.setAutoscrolls(true);
setViewportView(list);
}
else
{
table = new TableView(app, el == null ? /* design component */null : el.getFormController(), form, meta, el, null, null, printing);
table.setOpaque(false);
dal = table.getDataAdapterList();
editorComponents = table.getEditorComponents();
rendererComponents = table.getRendererComponents();
java.awt.Color bg = meta.getBackground();
if (bg != null)
{
getViewport().setBackground(bg);
table.setBackground(bg);
}
setViewportView(table);
// This is needed: http://forum.java.sun.com/thread.jspa?threadID=5148112&messageID=9751601
table.setFocusCycleRoot(true);
InputMap im = this.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK), ACTION_GO_OUT_TO_NEXT);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK + InputEvent.SHIFT_DOWN_MASK), ACTION_GO_OUT_TO_PREV);
ActionMap am = this.getActionMap();
am.put(ACTION_GO_OUT_TO_NEXT, new GoOutOfPortalComponentAction(false));
am.put(ACTION_GO_OUT_TO_PREV, new GoOutOfPortalComponentAction(true));
addJumpOutActionToComponent(table, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK), ACTION_GO_OUT_TO_NEXT, false);
addJumpOutActionToComponent(table, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK),
ACTION_GO_OUT_TO_PREV, true);
}
addMouseListener(new MouseAdapter()
{
@Override
public void mouseReleased(MouseEvent e)
{
application.getFoundSetManager().getEditRecordList().stopEditing(false);
}
});
ComponentFactory.applyBasicComponentProperties(application, this, meta, ComponentFactory.getStyleForBasicComponent(application, meta, form));
try
{
Relation[] relations = application.getFlattenedSolution().getRelationSequence(meta.getRelationName());
if (relations != null)
{
relationName = meta.getRelationName();
defaultSort = ((FoundSetManager)app.getFoundSetManager()).getSortColumns(relations[relations.length - 1].getForeignTable(),
meta.getInitialSort());
}
}
catch (RepositoryException e)
{
Debug.error(e);
defaultSort = new ArrayList<SortColumn>(1);
}
setFocusCycleRoot(true);
setFocusTraversalPolicy(ServoyFocusTraversalPolicy.datarenderPolicy);
addFocusListener(new AutoTransferFocusListener(this, this));
this.scriptable = scriptable;
scriptable.setJComponent(list != null ? list : table);
}
public final RuntimePortal getScriptObject()
{
return scriptable;
}
// TODO: probably these should also be removed from the component at some point?
private void addJumpOutActionToComponent(JComponent c, KeyStroke key, String actionName, boolean moveBackward)
{
if (!moveBackward)
{
Set originalForwardKeys = c.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
Set newForwardKeys = new HashSet(originalForwardKeys);
if (newForwardKeys.contains(key)) newForwardKeys.remove(key);
c.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
}
else
{
Set originalBackwardKeys = c.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
Set newBackwardKeys = new HashSet(originalBackwardKeys);
if (newBackwardKeys.contains(key)) newBackwardKeys.remove(key);
c.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, newBackwardKeys);
}
InputMap im = c.getInputMap(WHEN_FOCUSED);
im.put(key, actionName);
ActionMap am = c.getActionMap();
am.put(actionName, new GoOutOfPortalComponentAction(moveBackward));
}
public Component[] getEditorComponents()
{
if (table != null)
{
return editorComponents;
}
else
{
return editor.getComponents();
}
}
public Component[] getRendererComponents()
{
if (table != null)
{
return rendererComponents;
}
else
{
return renderer.getComponents();
}
}
public JComponent getRealComponent()
{
if (table != null) return table;
return list;
}
public int getPreferredBreak(int preferredBreak)
{
if (currentData == null) return preferredBreak;
int retval = preferredBreak;
int i = 0;
Rectangle r = new Rectangle();
if (table != null)
{
if (table.getTableHeader() != null)
{
preferredBreak -= table.getTableHeader().getHeight();
retval = preferredBreak;
}
while (i < currentData.getSize() && r != null && r.y <= preferredBreak)
{
r = table.getCellRect(i++, 0, true);
if (r != null && r.y <= preferredBreak)
{
retval = r.y;
}
else
{
break;
}
}
if (table.getTableHeader() != null)
{
retval += table.getTableHeader().getHeight();
}
}
else
{
while (i < currentData.getSize() && r != null && r.y <= preferredBreak)
{
r = list.getCellBounds(i++, i);
if (r != null && r.y <= preferredBreak)
{
retval = r.y;
}
else
{
break;
}
}
}
return retval;
}
public void destroy()
{
setRecord(null, false);//safety
if (dal != null)
{
dal.destroy();
dal = null;
}
if (table != null)
{
TableColumnModel tcm = table.getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++)
{
CellAdapter ca = (CellAdapter)tcm.getColumn(i);
Object o = ca.getEditor();
if (o instanceof IDestroyable)
{
((IDestroyable)o).destroy();
}
o = ca.getRenderer();
if (o instanceof IDestroyable)
{
((IDestroyable)o).destroy();
}
}
}
if (renderer != null)
{
renderer.destroy();
renderer = null;
}
if (editor != null)
{
editor.destroy();
editor = null;
}
}
@Override
public Rectangle getBounds()
{
boolean isPrinting = Utils.getAsBoolean(application.getRuntimeProperties().get("isPrinting")); //$NON-NLS-1$
if (isPrinting && currentData != null)
{
if (((FoundSet)currentData).hadMoreRows())
{
((FoundSet)currentData).queryForAllPKs();
}
currentData.getSelectionModel().hideSelectionForPrinting();
}
return super.getBounds();
}
@Override
public void setUI(ComponentUI ui)
{
super.setUI(ui);
}
public void setValidationEnabled(boolean b)
{
if (dal != null) dal.setFindMode(!b);
}
private ISwingFoundSet currentData;
public void setRecord(IRecordInternal state, boolean stopEditing)
{
if (stopEditing)
{
stopUIEditing(true);
}
IFoundSetInternal relatedFoundSet = state == null ? null : state.getRelatedFoundSet(relationName, getDefaultSort());
if (currentData == relatedFoundSet) return;//if is same changes are seen by model listener
if (currentData != null)
{
currentData.removeTableModelListener(this);
ListSelectionModel lsm = currentData.getSelectionModel();
lsm.removeListSelectionListener(this);
}
currentData = (ISwingFoundSet)relatedFoundSet;
ISupportOnRenderCallback portalRenderComponent = null;
if (table != null)
{
if (currentData == null)
{
table.removeEditor();//safety
table.setSelectionModel(EMPTY_SELECTION);
table.setModel(EMPTY_DATA);
}
else
{
ListSelectionModel lsm = currentData.getSelectionModel();
int selected = currentData.getSelectedIndex();
table.setSelectionModel(lsm);
table.setModel((IFoundSetInternal)currentData);
currentData.setSelectedIndex(selected);
currentData.addTableModelListener(this);
lsm.addListSelectionListener(this);
valueChanged(null, stopEditing);
}
portalRenderComponent = table.getOnRenderComponent();
}
else
{
if (currentData == null)
{
list.setSelectionModel(EMPTY_SELECTION);
list.setModel(new AbstractEditListModel()
{
public Object getElementAt(int i)
{
return null;
}
public int getSize()
{
return 0;
}
});
}
else
{
list.setSelectionModel(EMPTY_SELECTION);
ListSelectionModel lsm = currentData.getSelectionModel();
list.setModel(currentData);
list.setSelectionModel(lsm);
currentData.addTableModelListener(this);
lsm.addListSelectionListener(this);
valueChanged(null, stopEditing);
}
portalRenderComponent = list.getOnRender();
}
scriptable.setFoundset(currentData);
if (currentData != null && portalRenderComponent != null && portalRenderComponent.getRenderEventExecutor().hasRenderCallback())
{
portalRenderComponent.getRenderEventExecutor().setRenderState(null, -1, false, true);
portalRenderComponent.getRenderEventExecutor().fireOnRender(false);
}
}
public String getSelectedRelationName()
{
return relationName;
}
public String[] getAllRelationNames()
{
String relationName = getSelectedRelationName();
if (relationName == null)
{
return new String[0];
}
else
{
return new String[] { relationName };
}
}
public void notifyVisible(boolean b, List invokeLaterRunnables)
{
if (dal != null)
{
dal.notifyVisible(b, invokeLaterRunnables);
}
}
public boolean stopUIEditing(boolean looseFocus)
{
if (table != null && table.isEditing())
{
CellEditor ce = table.getCellEditor();
if (ce != null && !ce.stopCellEditing()) return false;
}
else if (list != null && list.isEditing())
{
CellEditor ce = list.getCellEditor();
if (ce != null && !ce.stopCellEditing()) return false;
}
if (dal != null) return dal.stopUIEditing(looseFocus);
return true;
}
public void valueChanged(ListSelectionEvent e)
{
valueChanged(e, true);
}
private int lastAdjusting;
private void valueChanged(ListSelectionEvent eventCanBeNull, boolean stopAnyEdit)
{
IFoundSetInternal s = null;
if (table != null)
{
TableModel tm = table.getModel();
if (tm instanceof IFoundSetInternal)
{
s = (IFoundSetInternal)tm;
}
}
else
{
ListModel tm = list.getModel();
if (tm instanceof IFoundSetInternal)
{
s = (IFoundSetInternal)tm;
}
}
if (s != null)
{
if (dal != null)
{
int index = getRecordIndex();
if (index != -1)
{
IRecordInternal state = s.getRecord(index);
if (state != null)//can happen when notified from client and itself not having a selection yet
{
if (eventCanBeNull != null && eventCanBeNull.getValueIsAdjusting())
{
if (lastAdjusting != index)
{
lastAdjusting = index;
application.getFoundSetManager().getEditRecordList().stopIfEditing(s);
}
}
else
{
lastAdjusting = -1;
dal.setRecord(state, stopAnyEdit);
}
}
else
{
dal.setRecord(null, stopAnyEdit);
}
}
else
{
dal.setRecord(null, stopAnyEdit);
}
}
}
}
private String rowBGColorScript;
private List<Object> rowBGColorArgs;
public void setRowBGColorScript(String str, List<Object> args)
{
rowBGColorScript = str;
rowBGColorArgs = args;
}
public String getRowBGColorScript()
{
return rowBGColorScript;
}
public List<Object> getRowBGColorArgs()
{
return rowBGColorArgs;
}
private int getRecordIndex()
{
if (table != null)
{
return table.getSelectedRow();
}
else
{
return list.getSelectedIndex();
}
}
public void setRecordIndex(int i)
{
if (table != null)
{
table.getSelectionModel().setSelectionInterval(i, i);
Rectangle cellRect = table.getCellRect(i, 0, false);
if (cellRect != null)
{
table.scrollRectToVisible(cellRect);
}
}
else
{
list.setSelectedIndex(i);
list.ensureIndexIsVisible(i);
}
}
@Override
public void setBackground(Color c)
{
super.setBackground(c);
getViewport().setBackground(c);
if (table != null)
{
table.setBackground(c);
}
else
{
if (list != null) list.setBackground(c);
if (renderer != null) renderer.setBackground(c);
if (editor != null) editor.setBackground(c);
}
}
@Override
public void setForeground(Color c)
{
getViewport().setForeground(c);
if (table != null)
{
// table.setForeground(c);
}
else
{
if (list != null) list.setForeground(c);
if (renderer != null) renderer.setForeground(c);
if (editor != null) editor.setForeground(c);
}
}
public void setComponentEnabled(final boolean b)
{
if (accessible)
{
super.setEnabled(b);
if (table != null)
{
if (!b) table.setEnabled(b);
}
else
{
if (!b) list.setEnabled(b);
}
}
}
private boolean accessible = true;
public void setAccessible(boolean b)
{
if (!b) setComponentEnabled(b);
accessible = b;
}
private boolean viewable = true;
public void setViewable(boolean b)
{
if (!b) setComponentVisible(b);
this.viewable = b;
}
public boolean isViewable()
{
return viewable;
}
public boolean isReadOnly()
{
if (list != null)
{
return !list.isEditable();
}
else
{
return !table.isEditable();
}
}
public void setReadOnly(boolean b)
{
if (list != null)
{
list.setEditable(!b);
}
else
{
table.setEditable(!b);
}
}
public int getAbsoluteFormLocationY()
{
Container parent = getParent();
while ((parent != null) && !(parent instanceof IDataRenderer))
{
parent = parent.getParent();
}
if (parent != null)
{
return ((IDataRenderer)parent).getYOffset() + getLocation().y;
}
return getLocation().y;
}
/*
* visible---------------------------------------------------
*/
public void setComponentVisible(boolean b)
{
if (viewable)
{
setVisible(b);
}
}
public List<SortColumn> getDefaultSort()
{
return defaultSort;
}
public void tableChanged(TableModelEvent e)
{
boolean isEditing = false;
if (table != null)
{
isEditing = table.isEditing();
}
else
{
isEditing = list.isEditing();
}
if (isEditing && e.getType() == TableModelEvent.DELETE)
{
if (e.getFirstRow() >= currentData.getSelectedIndex() && currentData.getSelectedIndex() <= e.getLastRow())
{
stopUIEditing(true);
}
}
else if (isEditing && e.getType() == TableModelEvent.INSERT)
{
stopUIEditing(true);
}
int index = getRecordIndex();//is Selected Index
if (e.getFirstRow() == index)
{
valueChanged(null, false);//fire value chance becouse selection does not fire
}
}
public void toXML(Writer w, Rectangle rec) throws IOException
{
if (currentData != null)
{
w.write("<ROWSCOMPONENT x=\"" + rec.x + "\" y=\"" + rec.y + "\" width=\"" + rec.width + "\" height=\"" + rec.height + "\" >"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
if (table == null)
{
w.write("<ROWS count=\"" + currentData.getSize() + "\" >"); //$NON-NLS-1$ //$NON-NLS-2$
DataRenderer formRenderer = (DataRenderer)list.getCellRenderer();
for (int ii = 0; ii < currentData.getSize(); ii++)
{
w.write("<ROW>"); //$NON-NLS-1$
IRecordInternal state = currentData.getRecord(ii);
formRenderer.getDataAdapterList().setRecord(state, true);
Component[] comps = formRenderer.getComponents();
for (Component component : comps)
{
XMLPrintHelper.handleComponent(w, component, component.getBounds(), null);
}
w.write("</ROW>"); //$NON-NLS-1$
}
w.write("</ROWS>"); //$NON-NLS-1$
}
else
{
w.write("<ROWS count=\"" + currentData.getSize() + "\" >"); //$NON-NLS-1$//$NON-NLS-2$
for (int ii = 0; ii < currentData.getSize(); ii++)
{
w.write("<ROW>"); //$NON-NLS-1$
IRecordInternal state = currentData.getRecord(ii);
TableColumnModel tcm = table.getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++)
{
CellAdapter ca = (CellAdapter)tcm.getColumn(i);
String dataProviderID = ca.getDataProviderID();
Component component = ca.getRenderer();
XMLPrintHelper.handleComponent(w, component, component.getBounds(), state.getValue(dataProviderID));
}
w.write("</ROW>"); //$NON-NLS-1$
}
w.write("</ROWS>"); //$NON-NLS-1$
}
w.write("</ROWSCOMPONENT>"); //$NON-NLS-1$
}
}
@Override
public void setOpaque(boolean isOpaque)
{
if (table != null)
{
table.getTableHeader().setOpaque(isOpaque);
}
else if (list != null)
{
list.setOpaque(isOpaque);
}
getViewport().setOpaque(isOpaque);
super.setOpaque(isOpaque);
}
@Override
public void addNotify()
{
super.addNotify();
if (getColumnHeader() != null && isOpaque() != getColumnHeader().isOpaque()) this.getColumnHeader().setOpaque(isOpaque());
}
/**
* @param javaObject
* @todo Generated comment
*/
public void editCellFor(JComponent javaObject)
{
if (table != null)
{
int selectedRow = table.getSelectedRow();
for (int i = 0; i < table.getColumnCount(); i++)
{
if (((CellAdapter)table.getCellEditor(selectedRow, i)).getEditor() == javaObject)
{
table.editCellAt(selectedRow, i);
break;
}
}
}
else if (list != null)
{
list.editCellAt(list.getSelectedIndex());
javaObject.requestFocus();
}
}
@Override
public String toString()
{
return "PortalComponent[" + getName() + ":" + getBounds();//$NON-NLS-1$ //$NON-NLS-2$
}
public String getId()
{
return (String)getClientProperty("Id");
}
@Override
protected void printChildren(Graphics g)
{
super.printChildren(g);
super.printBorder(g); // print border after children print, to prevent child backgrounds ontop of border
}
@Override
protected void printBorder(Graphics g)
{
//intentionally empty to have the border drawn after the content
}
public boolean isTraversalPolicyEnabled()
{
return true;
}
public Component getFirstFocusableField()
{
return getViewport().getView();
}
public Component getLastFocusableField()
{
return getViewport().getView();
}
public List<Component> getTabSeqComponents()
{
List<Component> tabSeq = new ArrayList<Component>();
tabSeq.add(getViewport().getView());
return tabSeq;
}
public void setTabSeqComponents(List<Component> tabSequence)
{
// ignore
}
public boolean isTransferFocusBackwards()
{
return transferFocusBackwards;
}
public void setTransferFocusBackwards(boolean transferBackwards)
{
this.transferFocusBackwards = transferBackwards;
}
private class GoOutOfPortalComponentAction extends AbstractAction
{
private final boolean moveBackward;
public GoOutOfPortalComponentAction(boolean moveBackward)
{
this.moveBackward = moveBackward;
}
public void actionPerformed(ActionEvent e)
{
PortalComponent.this.setTransferFocusBackwards(moveBackward);
KeyboardFocusManager.getCurrentKeyboardFocusManager().upFocusCycle();
}
}
private IStyleSheet styleSheet;
private IStyleRule oddStyle;
private IStyleRule evenStyle;
private IStyleRule selectedStyle;
private IStyleRule headerStyle;
/*
* @see com.servoy.j2db.ui.ISupportOddEvenStyling#setStyles(javax.swing.text.html.StyleSheet, javax.swing.text.Style, javax.swing.text.Style)
*/
public void setRowStyles(IStyleSheet styleSheet, IStyleRule oddStyle, IStyleRule evenStyle, IStyleRule selectedStyle, IStyleRule headerStyle)
{
this.styleSheet = styleSheet;
this.oddStyle = oddStyle;
this.evenStyle = evenStyle;
this.selectedStyle = selectedStyle;
this.headerStyle = headerStyle;
if (table != null)
{
table.setRowStyles(styleSheet, oddStyle, evenStyle, selectedStyle, headerStyle);
}
else if (list != null)
{
list.setRowStyles(styleSheet, oddStyle, evenStyle, selectedStyle, headerStyle);
if (oddStyle != null || evenStyle != null)
{
for (Component c : renderer.getComponents())
{
if (c instanceof JComponent) ((JComponent)c).setOpaque(false);
}
for (Component c : editor.getComponents())
{
if (c instanceof JComponent) ((JComponent)c).setOpaque(false);
}
}
}
}
public IStyleSheet getRowStyleSheet()
{
return styleSheet;
}
public IStyleRule getRowOddStyle()
{
return oddStyle;
}
public IStyleRule getRowEvenStyle()
{
return evenStyle;
}
public IStyleRule getRowSelectedStyle()
{
return selectedStyle;
}
public IStyleRule getHeaderStyle()
{
return headerStyle;
}
private void addOnRender(IDisplay display, Portal portal, IPersist portalObj, IScriptExecuter el)
{
if (display instanceof IScriptableProvider)
{
IScriptable s = ((IScriptableProvider)display).getScriptObject();
if (s instanceof ISupportOnRenderCallback && ((ISupportOnRenderCallback)s).getRenderEventExecutor() != null)
{
ComponentFactoryHelper.addPortalOnRenderCallback(portal, ((ISupportOnRenderCallback)s).getRenderEventExecutor(), portalObj, el);
}
}
}
private class PortalMultilineList extends JEditList implements ISupportRowStyling, ISupportOnRenderWrapper
{
private final ISupportOnRenderCallback dataRendererOnRenderWrapper;
private final Portal portal;
private IStyleSheet ss;
private IStyleRule oStyle;
private IStyleRule eStyle;
private IStyleRule sStyle;
private IStyleRule hStyle;
PortalMultilineList(Portal portal, IScriptExecuter se)
{
this.portal = portal;
dataRendererOnRenderWrapper = new DataRendererOnRenderWrapper(this);
int onRenderMethodID = portal.getOnRenderMethodID();
if (onRenderMethodID > 0)
{
dataRendererOnRenderWrapper.getRenderEventExecutor().setRenderCallback(Integer.toString(onRenderMethodID),
Utils.parseJSExpressions(portal.getInstanceMethodArguments("onRenderMethodID")));
dataRendererOnRenderWrapper.getRenderEventExecutor().setRenderScriptExecuter(se);
}
}
public ISupportOnRenderCallback getOnRender()
{
return dataRendererOnRenderWrapper;
}
public void setRowStyles(IStyleSheet styleSheet, IStyleRule oddStyle, IStyleRule evenStyle, IStyleRule selectedStyle, IStyleRule headerStyle)
{
this.ss = styleSheet;
this.oStyle = oddStyle;
this.eStyle = evenStyle;
this.sStyle = selectedStyle;
this.hStyle = headerStyle;
}
public IStyleSheet getRowStyleSheet()
{
return ss;
}
public IStyleRule getRowOddStyle()
{
return oStyle;
}
public IStyleRule getRowEvenStyle()
{
return eStyle;
}
/*
* @see com.servoy.j2db.ui.ISupportOnRenderWrapper#getOnRenderComponent()
*/
public ISupportOnRenderCallback getOnRenderComponent()
{
return dataRendererOnRenderWrapper;
}
/*
* @see com.servoy.j2db.ui.ISupportOnRenderWrapper#getOnRenderElementType()
*/
public String getOnRenderElementType()
{
return IRuntimeComponent.PORTAL;
}
/*
* @see com.servoy.j2db.ui.ISupportOnRenderWrapper#getOnRenderToString()
*/
public String getOnRenderToString()
{
return portal.toString();
}
/*
* @see com.servoy.j2db.ui.ISupportRowStyling#getSelectedStyle()
*/
public IStyleRule getRowSelectedStyle()
{
return sStyle;
}
public IStyleRule getHeaderStyle()
{
return hStyle;
}
}
}