/*
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;
import java.awt.AWTKeyStroke;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.KeyboardFocusManager;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.print.PrinterJob;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
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.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.text.html.CSS;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.mozilla.javascript.JavaMembers;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import com.servoy.base.scripting.api.IJSEvent.EventType;
import com.servoy.j2db.ControllerUndoManager;
import com.servoy.j2db.DesignModeCallbacks;
import com.servoy.j2db.FormController;
import com.servoy.j2db.FormManager;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.IForm;
import com.servoy.j2db.IFormUIInternal;
import com.servoy.j2db.ISmartClientApplication;
import com.servoy.j2db.IView;
import com.servoy.j2db.Messages;
import com.servoy.j2db.component.ComponentFactory;
import com.servoy.j2db.component.ISupportAsyncLoading;
import com.servoy.j2db.dataprocessing.BufferedDataSet;
import com.servoy.j2db.dataprocessing.FoundSetManager;
import com.servoy.j2db.dataprocessing.IDataSet;
import com.servoy.j2db.dataprocessing.IDisplay;
import com.servoy.j2db.dataprocessing.IFoundSetInternal;
import com.servoy.j2db.dataprocessing.ISaveConstants;
import com.servoy.j2db.dataprocessing.JSDataSet;
import com.servoy.j2db.dataprocessing.PrototypeState;
import com.servoy.j2db.dataprocessing.SortColumn;
import com.servoy.j2db.dataui.IServoyAwareBean;
import com.servoy.j2db.dnd.DRAGNDROP;
import com.servoy.j2db.gui.FormDialog;
import com.servoy.j2db.persistence.FormElementGroup;
import com.servoy.j2db.persistence.Part;
import com.servoy.j2db.persistence.Table;
import com.servoy.j2db.printing.FormPreviewPanel;
import com.servoy.j2db.printing.PageList;
import com.servoy.j2db.printing.PrintPreview;
import com.servoy.j2db.scripting.ElementScope;
import com.servoy.j2db.scripting.IScriptable;
import com.servoy.j2db.scripting.IScriptableProvider;
import com.servoy.j2db.scripting.JSEvent;
import com.servoy.j2db.scripting.RuntimeGroup;
import com.servoy.j2db.scripting.ScriptObjectRegistry;
import com.servoy.j2db.scripting.info.CLIENTDESIGN;
import com.servoy.j2db.smart.dataui.CellAdapter;
import com.servoy.j2db.smart.dataui.DataComboBox;
import com.servoy.j2db.smart.dataui.DataRenderer;
import com.servoy.j2db.smart.dataui.FormBodyEditor;
import com.servoy.j2db.smart.dataui.FormLookupPanel;
import com.servoy.j2db.smart.dataui.InvisibleBean;
import com.servoy.j2db.smart.dataui.PortalComponent;
import com.servoy.j2db.smart.dataui.ScriptButton;
import com.servoy.j2db.smart.dataui.ScriptLabel;
import com.servoy.j2db.smart.dataui.SpecialSplitPane;
import com.servoy.j2db.smart.dataui.SpecialTabPanel;
import com.servoy.j2db.smart.dataui.SplitPane;
import com.servoy.j2db.smart.dataui.StyledEnablePanel;
import com.servoy.j2db.smart.dataui.VisibleBean;
import com.servoy.j2db.smart.scripting.TwoNativeJavaObject;
import com.servoy.j2db.ui.IComponent;
import com.servoy.j2db.ui.IDataRenderer;
import com.servoy.j2db.ui.ITabPanel;
import com.servoy.j2db.ui.runtime.HasRuntimeReadOnly;
import com.servoy.j2db.ui.runtime.IRuntimeComponent;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.EnablePanel;
import com.servoy.j2db.util.IFocusCycleRoot;
import com.servoy.j2db.util.IStyleRule;
import com.servoy.j2db.util.IStyleSheet;
import com.servoy.j2db.util.ISupportFocusTransfer;
import com.servoy.j2db.util.ITabPaneAlike;
import com.servoy.j2db.util.OrientationApplier;
import com.servoy.j2db.util.Pair;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.gui.AutoTransferFocusListener;
import com.servoy.j2db.util.gui.KeyReleaseActionJButton;
import com.servoy.j2db.util.gui.PartsScrollPane;
public class SwingForm extends PartsScrollPane implements IFormUIInternal<Component>, ISupportFocusTransfer
{
private static final long serialVersionUID = 1L;
private static final String ACTION_GO_OUT_TO_NEXT = "goOutToNext"; //$NON-NLS-1$
private static final String ACTION_GO_OUT_TO_PREV = "goOutToPrev"; //$NON-NLS-1$
private final ControllerUndoManager undoManager;
private final FormController formController;
private List<Component> tabSeqComponentList = new ArrayList<Component>();
private boolean transferFocusBackwards = false;
private boolean readonly;
private IView view;
private final List<Component> componentsWithEditableStateChanged = new ArrayList<Component>();
private final List<Component> componentsWithEnabledStateChanged = new ArrayList<Component>();
private Color bgColor;
private final Timer containerTimer;
public SwingForm(FormController formController)
{
this.formController = formController;
setFocusCycleRoot(true);
ComponentFactory.applyScrollBarsProperty(this, formController.getForm());
undoManager = new ControllerUndoManager();
undoManager.setLimit(50);
// everything transparent, because of semitransparency support
boolean isTransparent = formController.getForm().getTransparent();
setOpaque(!isTransparent);
// if (isTransparent) setBackground(new Color(0, 0, 0, 254)); // TODO remove this if it also works without it on Ubuntu
ActionMap am = this.getActionMap();
am.put(ACTION_GO_OUT_TO_NEXT, new GoOutOfSwingFormAction(false));
am.put(ACTION_GO_OUT_TO_PREV, new GoOutOfSwingFormAction(true));
addFocusListener(new AutoTransferFocusListener(this, this));
readonly = false;
registerFindKeystrokes(this);
containerTimer = new Timer(300, new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
try
{
if (SwingForm.this.formController != null)
{
SwingForm.this.formController.notifyResized();
}
}
finally
{
containerTimer.stop();
}
}
});
addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent e)
{
containerTimer.start();
}
});
}
private void registerFindKeystrokes(JComponent c)
{
Action a = formController.getApplication().getCmdManager().getRegisteredAction("cmdperformfind"); //$NON-NLS-1$
if (a != null)
{
c.registerKeyboardAction(a, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
a = formController.getApplication().getCmdManager().getRegisteredAction("cmdstopsearchfindall"); //$NON-NLS-1$
if (a != null)
{
c.registerKeyboardAction(a, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
}
// 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<AWTKeyStroke> originalForwardKeys = c.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
Set<AWTKeyStroke> newForwardKeys = new HashSet<AWTKeyStroke>(originalForwardKeys);
if (newForwardKeys.contains(key)) newForwardKeys.remove(key);
c.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, newForwardKeys);
}
else
{
Set<AWTKeyStroke> originalBackwardKeys = c.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
Set<AWTKeyStroke> newBackwardKeys = new HashSet<AWTKeyStroke>(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 GoOutOfSwingFormAction(moveBackward));
}
public void setTabSeqComponents(List<Component> tabSequence)
{
IDataRenderer formEditorRenderer = formController.getDataRenderers()[FormController.FORM_EDITOR];
if (formEditorRenderer instanceof TableView && (tabSequence == null || !tabSequence.contains(formEditorRenderer)))
{
// table view should be added to tab sequence
((TableView)formEditorRenderer).setTabSeqComponents(tabSequence);
if (tabSequence != null && tabSequence.size() > 0)
{
// this means that we have to identify components that are part of the table view and based on where these are located set the view's tabIndex
// when called from JS tabSequence will only contain table columns, not table view as opposed to initialization when tabSequence only contains the view
int i;
for (i = 0; i < tabSequence.size(); i++)
{
if (((TableView)formEditorRenderer).isColumnIdentifierComponent(tabSequence.get(i)))
{
tabSequence = new ArrayList<Component>(tabSequence);
tabSequence.add(i, (Component)formEditorRenderer);
break;
}
}
i++;
while (i < tabSequence.size())
{
if (((TableView)formEditorRenderer).isColumnIdentifierComponent(tabSequence.get(i)))
{
tabSequence.remove(i);
}
else
{
i++;
}
}
}
}
this.tabSeqComponentList = tabSequence;
if (tabSeqComponentList != null)
{
if (tabSeqComponentList.size() > 0)
{
JComponent lastComponent = (JComponent)tabSeqComponentList.get(tabSeqComponentList.size() - 1);
if (!(lastComponent instanceof SpecialTabPanel))
{
int modifier = 0;
if ((lastComponent instanceof TableView)) modifier = InputEvent.CTRL_DOWN_MASK;
if ((lastComponent instanceof DataComboBox) && ((DataComboBox)lastComponent).isEditable()) lastComponent = (JComponent)((DataComboBox)lastComponent).getEditor().getEditorComponent();
addJumpOutActionToComponent(lastComponent, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, modifier), ACTION_GO_OUT_TO_NEXT, false);
}
JComponent firstComponent = (JComponent)tabSeqComponentList.get(0);
if (!(firstComponent instanceof SpecialTabPanel))
{
int modifier = 0;
if ((firstComponent instanceof TableView)) modifier = InputEvent.CTRL_DOWN_MASK;
if ((firstComponent instanceof DataComboBox) && ((DataComboBox)firstComponent).isEditable()) firstComponent = (JComponent)((DataComboBox)firstComponent).getEditor().getEditorComponent();
addJumpOutActionToComponent(firstComponent, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, modifier | InputEvent.SHIFT_DOWN_MASK),
ACTION_GO_OUT_TO_PREV, true);
}
}
}
}
public List<Component> getTabSeqComponents()
{
return tabSeqComponentList;
}
public void focusField(Component field)
{
Component fieldToFocus = field;
if (fieldToFocus instanceof SpecialTabPanel)
{
Object potential = ((SpecialTabPanel)fieldToFocus).getFirstFocusableField();
if (potential != null)
{
fieldToFocus = (Component)potential;
if (fieldToFocus instanceof IFocusCycleRoot< ? >)
{
potential = ((IFocusCycleRoot< ? >)fieldToFocus).getFirstFocusableField();
if (potential != null) fieldToFocus = (Component)potential;
}
}
}
if (fieldToFocus instanceof TableView)
{
((TableView)fieldToFocus).editCellAt(((TableView)fieldToFocus).getSelectedRow());
}
else if (fieldToFocus != null)
{
if (view instanceof ListView)
{
view.editCellAt(((ListView)view).getSelectedIndex());
}
fieldToFocus.requestFocus();
}
}
public Component getFirstFocusableField()
{
if (view instanceof ListView && !((ListView)view).isEditing())
{
view.editCellAt(((ListView)view).getSelectedIndex());
}
if (tabSeqComponentList != null && tabSeqComponentList.size() > 0)
{
return tabSeqComponentList.get(0);
}
return null;
}
public Component getLastFocusableField()
{
if (tabSeqComponentList != null && tabSeqComponentList.size() > 0)
{
return tabSeqComponentList.get(tabSeqComponentList.size() - 1);
}
return null;
}
public JSDataSet getFormContext()
{
SwingForm current = this;
FormLookupPanel currentLookupPanel = null;
SpecialTabPanel currentTabPanel = null;
String currentBeanName = null;
SpecialSplitPane currentSplitPane = null;
IDataSet set = new BufferedDataSet(
new String[] { "containername", "formname", "tabpanel/splitpane/accordion/beanname", "tabname", "tabindex", "tabindex1based" }, new ArrayList<Object[]>()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
set.addRow(new Object[] { null, current.formController.getName(), null, null, null, null });
Container parent = getParent();
while (parent != null)
{
if (parent instanceof SpecialTabPanel)
{
currentTabPanel = (SpecialTabPanel)parent;
}
else if (parent instanceof SpecialSplitPane)
{
currentSplitPane = (SpecialSplitPane)parent;
}
else if (parent instanceof FormLookupPanel)
{
currentLookupPanel = (FormLookupPanel)parent;
}
else if (parent instanceof IServoyAwareBean && parent instanceof IComponent)
{
currentBeanName = ((IComponent)parent).getName();
}
else if (parent instanceof SwingForm)
{
current = (SwingForm)parent;
if (currentTabPanel != null)
{
ITabPaneAlike panel = currentTabPanel.getEnclosingComponent();
int index = -1;
String tabName = null;
if (currentLookupPanel != null)
{
index = panel.getTabIndex(currentLookupPanel);
if (index != -1)
{
tabName = panel.getNameAt(index);
}
}
set.addRow(0, new Object[] { null, current.formController.getName(), currentTabPanel.getName(), tabName, new Integer(index), new Integer(
index + 1) });
}
else if (currentBeanName != null)
{
set.addRow(0, new Object[] { null, current.formController.getName(), currentBeanName, null, null, null });
}
else if (currentSplitPane != null)
{
int idx = currentLookupPanel != null && currentLookupPanel.equals(currentSplitPane.getLeftForm()) ? 0 : 1;
set.addRow(0,
new Object[] { null, current.formController.getName(), currentSplitPane.getName(), currentSplitPane.getTabNameAt(idx), new Integer(
idx + 1), new Integer(idx + 1) });
}
else
{
set.addRow(0, new Object[] { null, current.formController.getName(), null, null, null, null });
}
currentBeanName = null;
currentTabPanel = null;
currentLookupPanel = null;
currentSplitPane = null;
}
else if (parent instanceof MainPanel)
{
String containerName = ((MainPanel)parent).getContainerName();
if (containerName != null)
{
for (int i = 0; i < set.getRowCount(); i++)
{
set.getRow(i)[0] = containerName;
}
}
return new JSDataSet(formController.getApplication(), set);
}
parent = parent.getParent();
}
return new JSDataSet(formController.getApplication(), set);
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.IFormUIInternal#isReadOnly()
*/
@Override
public boolean isReadOnly()
{
return readonly;
}
/**
* TODO CHECK this one should always only be called Through the FormController!!
*
* @param b
*/
@Override
public void setReadOnly(boolean b)
{
readonly = b;
for (int i = 0; i < getComponentCount(); i++)
{
setReadOnly(getComponent(i), b);
}
// if (readonly != b)
// {
// readonly = b;
// if (readonly == true)
// {
// for (int i = 0; i < getComponentCount(); i++)
// {
// setReadOnly(getComponent(i), b);
// }
// }
// else
// {
// if (componentsWithEditableStateChanged.size() != 0)
// {
// for (Component component : componentsWithEditableStateChanged)
// {
// setReadOnly(component, b);
// }
// }
// componentsWithEditableStateChanged.clear();
// }
// }
// else
// {
// //set readOnly for all form children
// for (int i = 0; i < getComponentCount(); i++)
// {
// setReadOnlyOnFormChildren(getComponent(i), b);
// }
// }
}
private boolean componentIsReadOnly(Component comp)
{
if (comp instanceof ISupportEditStateTracking)
{
return !((ISupportEditStateTracking)comp).isEditable();
}
else if (comp instanceof IScriptableProvider && ((IScriptableProvider)comp).getScriptObject() instanceof HasRuntimeReadOnly)
{
return ((HasRuntimeReadOnly)((IScriptableProvider)comp).getScriptObject()).isReadOnly();
}
return false;
}
private void setReadOnly(Component comp, boolean b)
{
if (comp instanceof ISupportEditStateTracking)
{
if (b == true)
{
if (componentIsReadOnly(comp) == false)
{
((ISupportEditStateTracking)comp).setEditableWithStateTracking(false);
// if (componentsWithEditableStateChanged.contains(comp) == false) componentsWithEditableStateChanged.add(comp); // pay attention; what to do if container
}
}
else
{
((ISupportEditStateTracking)comp).setEditableWithStateTracking(true);
}
}
else if (comp instanceof IScriptableProvider && ((IScriptableProvider)comp).getScriptObject() instanceof HasRuntimeReadOnly)
{
((HasRuntimeReadOnly)((IScriptableProvider)comp).getScriptObject()).setReadOnly(b);
// if (b == true)
// {
// if (componentIsReadOnly(comp) == false)
// {
// ((HasRuntimeReadOnly)((IScriptableProvider)comp).getScriptObject()).setReadOnly(true);
// if (componentsWithEditableStateChanged.contains(comp) == false) componentsWithEditableStateChanged.add(comp); // pay attention; what to do if container
// }
// }
// else
// {
// ((HasRuntimeReadOnly)((IScriptableProvider)comp).getScriptObject()).setReadOnly(false);
// }
}
else if (comp instanceof Container)
{
Component[] comps = ((Container)comp).getComponents();
for (Component element : comps)
{
setReadOnly(element, b);
}
}
}
// private void setReadOnlyOnFormChildren(Component comp, boolean b)
// {
// if (comp instanceof Container)
// {
// if (comp instanceof SwingForm)
// {
// FormManager formManager = (FormManager)((SwingForm)comp).getController().getApplication().getFormManager();
// if (!formManager.isFormReadOnly(((SwingForm)comp).getController().getName()))
// {
// ((SwingForm)comp).getController().setReadOnly(b);
// }
// }
// else
// {
// Component[] comps = ((Container)comp).getComponents();
// for (Component element : comps)
// {
// setReadOnlyOnFormChildren(element, b);
// }
// }
// }
// }
@Override
public void setBackground(Color bgColor)
{
this.bgColor = bgColor;
if (bgColor != null)
{
JViewport viewport = getViewport();
if (viewport != null) viewport.setBackground(bgColor);
if (view instanceof ListView) ((ListView)view).setBackground(bgColor);
}
}
@Override
public void setOpaque(boolean isOpaque)
{
super.setOpaque(isOpaque);
JViewport viewport = getViewport();
if (viewport != null) viewport.setOpaque(isOpaque);
if (view instanceof ListView) ((ListView)view).setOpaque(isOpaque);
}
public IView initView(IApplication application, FormController fp, int viewType)
{
view = null;
IDataRenderer[] dataRenderers = fp.getDataRenderers();
setTitleHeader((JComponent)dataRenderers[Part.TITLE_HEADER]);
setHeader((JComponent)dataRenderers[Part.HEADER]);
setLeadingGrandSummary((JComponent)dataRenderers[Part.LEADING_GRAND_SUMMARY]);
setTrailingGrandSummary((JComponent)dataRenderers[Part.TRAILING_GRAND_SUMMARY]);
setFooter((JComponent)dataRenderers[Part.FOOTER]);
setWest(null);//remove any left slider
switch (viewType)
{
case FormController.LOCKED_LIST_VIEW :
case IForm.LIST_VIEW :
view = new ListView();
PrototypeState proto = null;
if (fp.getFoundSet() != null)
{
proto = fp.getFoundSet().getPrototypeState();
}
else
{
proto = new PrototypeState(null);
}
((ListView)view).setPrototypeCellValue(proto); //this call is extreemly inportant, it prevent all rows retrieval
FormBodyEditor editor = null;
if (dataRenderers[FormController.FORM_RENDERER] != null)
{
Component[] rendererComponents = ((Container)dataRenderers[FormController.FORM_RENDERER]).getComponents();
for (Component rendererComponent : rendererComponents)
{
if (rendererComponent instanceof ISupportAsyncLoading)
{
//in listview it is impossible to get lazy loaded images displaying correctly, due to needed repaintfire, which we cannot initiate
((ISupportAsyncLoading)rendererComponent).setAsyncLoadingEnabled(false);
}
rendererComponent.setFocusable(false);
}
((Component)dataRenderers[FormController.FORM_RENDERER]).setFocusable(false);
}
editor = new FormBodyEditor((DataRenderer)dataRenderers[FormController.FORM_EDITOR]);
if (dataRenderers[FormController.FORM_RENDERER] != null)
{
DataRenderer dr = (DataRenderer)dataRenderers[FormController.FORM_RENDERER];
dr.setRenderer(true);
String bgcolorCalc = fp.getForm().getRowBGColorCalculation();
if (bgcolorCalc != null)
{
//dr.setRowBGColorProvider(bgcolorCalc);
dr.setShowSelection(false);
((ListView)view).setRowBGColorScript(bgcolorCalc, fp.getForm().getInstanceMethodArguments("rowBGColorCalculation")); //$NON-NLS-1$
((DataRenderer)dataRenderers[FormController.FORM_EDITOR]).setShowSelection(false);
}
((ListView)view).setCellRenderer(dr);
}
else
{
// form with no body part - used only for printing probably
((ListView)view).setCellRenderer(new ListCellRenderer()
{
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
return new JLabel(""); //$NON-NLS-1$
}
});
}
((ListView)view).setCellEditor(editor);
((ListView)view).setRendererSameAsEditor(false);
((ListView)view).setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
break;
case FormController.LOCKED_TABLE_VIEW :
case FormController.TABLE_VIEW :
view = new TableView(application, fp, fp.getForm(), fp.getForm(), fp.getScriptExecuter(), dataRenderers[Part.HEADER],
dataRenderers[Part.LEADING_GRAND_SUMMARY], false);
if (dataRenderers[FormController.FORM_EDITOR] != null) dataRenderers[FormController.FORM_EDITOR].destroy();
dataRenderers[FormController.FORM_EDITOR] = (IDataRenderer)view;
if (formController.getBodyStyle() != null)
{
Pair<IStyleSheet, IStyleRule> pairStyle = ComponentFactory.getCSSPairStyleForForm(application, fp.getForm());
if (pairStyle != null && pairStyle.getLeft() != null)
{
Border border = pairStyle.getLeft().getBorder(formController.getBodyStyle());
if (border != null)
{
innerPanel.setBorder(border);
}
}
}
break;
case IForm.LOCKED_RECORD_VIEW :
case IForm.RECORD_VIEW :
default :
view = new RecordView(application);
if (dataRenderers[FormController.FORM_EDITOR] != null)
{
((DataRenderer)dataRenderers[FormController.FORM_EDITOR]).setShowSelection(false);
((RecordView)view).setCellRenderer((DataRenderer)dataRenderers[FormController.FORM_EDITOR]);
}
int form_id = fp.getForm().getNavigatorID();
if (form_id == 0)
{
StyledEnablePanel slider = ((RecordView)view).getSliderComponent();
if (bgColor != null) slider.setBackground(bgColor);
setWest(slider);
}
}
getVerticalScrollBar().setValue(1);
getVerticalScrollBar().setValue(0);
setViewportView((JComponent)view);
if (view instanceof TableView)
{
// the table view needs it's orientation set correctly
OrientationApplier.setOrientationToAWTComponent(this, application.getLocale(), application.getSolution().getTextOrientation());
}
if (view instanceof ListView)
{
view.requestFocus();
}
OrientationApplier.setOrientationToAWTComponent(this, application.getLocale(), application.getSolution().getTextOrientation());
if ((bgColor != null) && (view instanceof ListView)) ((ListView)view).setBackground(bgColor);
// revert semi transparency support
// ((JComponent)view).setOpaque(false);
// for (int i = FormController.FORM_RENDERER + 1; i < dataRenderers.length; i++)
// {
// if (dataRenderers[i] != null && !(dataRenderers[i] instanceof TableView))
// {
// dataRenderers[i].setOpaque(!formController.getForm().getTransparent());
// }
// }
// Apply the opacity to the newly added view (and slider if any),
// except if it's a table view, that is always transparent
if (!(view instanceof TableView))
{
setOpaque(isOpaque());
}
else
{
for (int i = FormController.FORM_RENDERER + 1; i < dataRenderers.length; i++)
{
if (dataRenderers[i] != null && !(dataRenderers[i] instanceof TableView))
{
dataRenderers[i].setOpaque(isOpaque());
}
}
}
return view;
}
@Override
public void destroy()
{
super.destroy();
Container p = getParent();
if (p != null)
{
p.remove(this);
}
}
public ControllerUndoManager getUndoManager()
{
return undoManager;
}
public FormController getController()
{
return formController;
}
public void setComponentVisible(boolean b_visible)
{
setVisible(b_visible);
}
public void setComponentEnabled(boolean enabled)
{
addEnabledComponents(this, componentsWithEnabledStateChanged);
if (!enabled) setEnabled(enabled);
else
{
for (Component component : componentsWithEnabledStateChanged)
{
if (component instanceof IComponent)
{
((IComponent)component).setComponentEnabled(enabled);
}
else component.setEnabled(enabled);
}
enablePanel(enabled);
componentsWithEnabledStateChanged.clear();
if (west != null)
{
west.setEnabled(enabled);
}
}
}
private void addEnabledComponents(Component parent, List<Component> components)
{
if (parent instanceof Container)
{
for (Component child : ((Container)parent).getComponents())
{
if ((child instanceof IScriptableProvider || child instanceof IScriptable || child instanceof ListView || child instanceof TableView ||
child instanceof EnablePanel || child instanceof DataRenderer || child instanceof SwingForm || child instanceof RecordView) &&
(child.isEnabled() || (child instanceof DataComboBox && ((DataComboBox)child).isComponentEnabled())))
{
components.add(child);
}
if (!(child instanceof IScriptableProvider))
{
addEnabledComponents(child, components);
}
}
}
}
public void showSortDialog(IApplication app, String options)
{
ISmartClientApplication application = (ISmartClientApplication)app;
try
{
Table t = (Table)formController.getTable();
if (t != null)
{
List<SortColumn> sortColumns = null;
if (options == null || options.length() == 0)
{
sortColumns = formController.getFormModel().getLastSortColumns();
}
else
{
sortColumns = ((FoundSetManager)application.getFoundSetManager()).getSortColumns(t, options);
}
Window window = SwingUtilities.getWindowAncestor(this);
if (window == null) window = application.getMainApplicationFrame();
SortDialog nfd = (SortDialog)application.getWindow("SortDialog"); //$NON-NLS-1$
if (nfd == null || nfd.getOwner() != window)
{
if (window instanceof Frame)
{
nfd = new SortDialog((Frame)window, application);
}
else if (window instanceof Dialog)
{
nfd = new SortDialog((Dialog)window, application);
}
application.registerWindow("SortDialog", nfd); //$NON-NLS-1$
}
List<SortColumn> list = nfd.showDialog(t, sortColumns);
if (list != null) formController.sort(list, false);
}
}
catch (Exception ex)
{
application.reportError(Messages.getString("servoy.formPanel.error.sortRecordsDialog"), ex); //$NON-NLS-1$
}
}
/**
* @see com.servoy.j2db.IFormUIInternal#makeElementsScriptObject(org.mozilla.javascript.Scriptable)
*/
public ElementScope makeElementsScriptObject(Scriptable fs, Map<String, Object[]> hmChildrenJavaMembers, IDataRenderer[] dataRenderers, IView controller)
{
ElementScope es = new ElementScope(fs);
int counter = 0;
for (int i = FormController.FORM_RENDERER + 1; i < dataRenderers.length; i++)
{
IDataRenderer dr = dataRenderers[i];
if (dr == null) continue;
Object[] comps = null;
Object[] compsRenderer = null;
if (dr instanceof DataRenderer)
{
comps = ((DataRenderer)dr).getComponents();
if (i == FormController.FORM_EDITOR && dataRenderers[FormController.FORM_RENDERER] != null)
{
compsRenderer = ((DataRenderer)dataRenderers[FormController.FORM_RENDERER]).getComponents();
}
}
else if (dr instanceof TableView)
{
TableView tv = (TableView)dr;
List<CellAdapter> nonViewableColumns = tv.getNonViewableColumns();
int componentCount = tv.getColumnCount() + nonViewableColumns.size();
comps = new Component[componentCount];
compsRenderer = new Component[componentCount];
CellAdapter[] tableCellAdapters = new CellAdapter[componentCount];
for (int j = 0; j < componentCount; j++)
{
tableCellAdapters[j] = (j < tv.getColumnCount()) ? (CellAdapter)tv.getCellEditor(0, j) : nonViewableColumns.get(j - tv.getColumnCount());
comps[j] = tableCellAdapters[j].getEditor();
compsRenderer[j] = tableCellAdapters[j].getRenderer();
}
for (int j = 0; j < comps.length; j++)
{
if (compsRenderer[j] instanceof Component && !((Component)compsRenderer[j]).isVisible())
{
tv.getColumnModel().removeColumn(tableCellAdapters[j]);
}
}
}
else if (dr instanceof WebMarkupContainer)
{
comps = new Object[((WebMarkupContainer)dr).size()];
Iterator< ? > it = ((WebMarkupContainer)dr).iterator();
int j = 0;
while (it.hasNext())
{
comps[j++] = it.next();
}
}
counter = registerComponentsToScope(fs, es, counter, comps, compsRenderer, (Component)controller, hmChildrenJavaMembers);
}
es.setLocked(true);
return es;
}
private int registerComponentsToScope(Scriptable fs, ElementScope es, int counter, Object[] comps, Object[] compsRenderer, Component controller,
Map<String, Object[]> hmChildrenJavaMembers)
{
if (comps != null)
{
for (int j = 0; j < comps.length; j++)
{
Object comp = comps[j];
if (comp instanceof PortalComponent)
{
PortalComponent portal = (PortalComponent)comp;
counter = registerComponentsToScope(fs, es, counter, portal.getEditorComponents(), portal.getRendererComponents(), portal,
hmChildrenJavaMembers);
}
String name = null;
if (comp instanceof IComponent)
{
name = ((IComponent)comp).getName();
}
else if (comp instanceof Component)
{
name = ((Component)comp).getName();
}
Object obj = comp;
if (comp instanceof InvisibleBean)
{
obj = ((InvisibleBean)comp).getDelegate();
}
else if (comp instanceof VisibleBean)
{
obj = ((VisibleBean)comp).getDelegate();
}
String groupName = FormElementGroup.getName((String)formController.getComponentProperty(comp, ComponentFactory.GROUPID_COMPONENT_PROPERTY));
if (obj instanceof IScriptableProvider) obj = ((IScriptableProvider)obj).getScriptObject();
IRuntimeComponent baseMethodsObj = null;
if (obj instanceof IRuntimeComponent)
{
baseMethodsObj = (IRuntimeComponent)obj;
}
JavaMembers jm = ScriptObjectRegistry.getJavaMembers(obj.getClass(), ScriptableObject.getTopLevelScope(fs));
boolean named = name != null && !name.equals("") && !name.startsWith(ComponentFactory.WEB_ID_PREFIX); //$NON-NLS-1$
if (groupName != null || named)
{
Object obj2 = null;
if (compsRenderer != null)
{
obj2 = compsRenderer[j];
if (obj2 instanceof InvisibleBean)
{
obj2 = ((InvisibleBean)obj2).getDelegate();
}
}
try
{
Scriptable s = null;
if (obj2 != null)
{
if (obj2 instanceof IScriptableProvider) obj2 = ((IScriptableProvider)obj2).getScriptObject();
NativeJavaObject s2 = new NativeJavaObject(fs, obj2, jm);
s = new TwoNativeJavaObject(fs, obj, s2, jm, controller);
// group properties have to be set to both
if (groupName != null && obj2 instanceof IRuntimeComponent)
{
if (baseMethodsObj == null)
{
baseMethodsObj = (IRuntimeComponent)obj2;
}
else
{
RuntimeGroup runtimeGroup = new RuntimeGroup(baseMethodsObj.getName());
runtimeGroup.addScriptBaseMethodsObj(baseMethodsObj);
runtimeGroup.addScriptBaseMethodsObj((IRuntimeComponent)obj2);
baseMethodsObj = runtimeGroup;
}
}
}
else
{
s = new NativeJavaObject(fs, obj, jm);
}
if (named)
{
es.put(name, fs, s);
es.put(counter++, fs, s);
hmChildrenJavaMembers.put(name, new Object[] { jm, obj });
}
if (groupName != null)
{
Object group = es.get(groupName, fs);
if (group == Scriptable.NOT_FOUND)
{
group = new NativeJavaObject(fs, new RuntimeGroup(groupName), ScriptObjectRegistry.getJavaMembers(RuntimeGroup.class,
ScriptableObject.getTopLevelScope(fs)));
es.put(groupName, fs, group);
es.put(counter++, fs, group);
}
if (baseMethodsObj != null && group instanceof NativeJavaObject && ((NativeJavaObject)group).unwrap() instanceof RuntimeGroup)
{
((RuntimeGroup)(((NativeJavaObject)group).unwrap())).addScriptBaseMethodsObj(baseMethodsObj);
}
}
}
catch (Throwable ex)
{
Debug.error(ex);//incase classdefnot founds are thrown for beans,applets/plugins
}
}
}
}
return counter;
}
/**
* @see com.servoy.j2db.IFormUIInternal#updateFormUI()
*/
public void updateFormUI()
{
invalidateTables(this);
}
@Override
public void touch()
{
}
private void invalidateTables(JComponent component)
{
int count = component.getComponentCount();
for (int i = 0; i < count; i++)
{
Component child = component.getComponent(i);
if (child instanceof JTable)
{
((JTable)child).repaint();
}
else if (child instanceof JComponent)
{
invalidateTables((JComponent)child);
}
}
}
/**
* @see com.servoy.j2db.IFormUIInternal#print(boolean, boolean, boolean, java.awt.print.PrinterJob)
*/
public void print(boolean showDialogs, boolean printCurrentRecordOnly, boolean showPrinterSelectDialog, PrinterJob printerJob)
{
IFoundSetInternal fs = formController.getFoundSet();
if (!printCurrentRecordOnly)
{
if (showDialogs)
{
int option = willingToPrint(fs);
if (option == 2)
{
printCurrentRecordOnly = true;
}
else if (option == 1)
{
return;//cancel
}
}
}
IApplication application = formController.getApplication();
try
{
application.blockGUI(Messages.getString("servoy.formPanel.status.printProgress")); //$NON-NLS-1$
if (printCurrentRecordOnly)
{
fs = fs.copyCurrentRecordFoundSet();
}
FormPreviewPanel fpp = new FormPreviewPanel(application, formController, fs);
fpp.process();
PrintPreview.startPrinting(application, fpp.getPageable(), printerJob, formController.getPreferredPrinterName(), showPrinterSelectDialog, false);
fpp.destroy();
}
catch (Exception ex)
{
application.reportError(Messages.getString("servoy.formPanel.error.printDocument"), ex); //$NON-NLS-1$
}
finally
{
application.releaseGUI();
}
}
/**
*
* @return 0 when ok,1 when cancel,2 when current rec.
*/
private int willingToPrint(IFoundSetInternal formModel)
{
//test if foundset is big. if so ask if really want to print/preview
if (formModel.getSize() >= ((FoundSetManager)formModel.getFoundSetManager()).pkChunkSize)
{
Object[] options = new String[] { Messages.getString("servoy.button.ok"), //$NON-NLS-1$
Messages.getString("servoy.button.cancel"), //$NON-NLS-1$
Messages.getString("servoy.formPanel.printCurrentRecord") //$NON-NLS-1$
};
ISmartClientApplication application = (ISmartClientApplication)formController.getApplication();
return JOptionPane.showOptionDialog(application.getMainApplicationFrame(),
Messages.getString("servoy.formPanel.message.largeResultset", new Object[] { new Integer(formModel.getSize()) }), //$NON-NLS-1$
Messages.getString("servoy.general.warning"), //$NON-NLS-1$
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
}
return 0;
}
/**
* @see com.servoy.j2db.IFormUIInternal#printPreview(boolean, boolean, java.awt.print.PrinterJob)
*/
public void printPreview(boolean showDialogs, boolean printCurrentRecordOnly, int zoomFactor, PrinterJob printerJob)
{
ISmartClientApplication application = (ISmartClientApplication)formController.getApplication();
try
{
// TODO do a print preview even if records are not saved?
if (application.getFoundSetManager().getEditRecordList().stopEditing(false) != ISaveConstants.STOPPED) return;
IFoundSetInternal set = formController.getFormModel();
if (set == null)
{
if (showDialogs)
{
JOptionPane.showMessageDialog(
application.getMainApplicationFrame(),
Messages.getString("servoy.formPanel.error.noRecordsToPrint"), Messages.getString("servoy.general.warning"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
}
return;
}
if (showDialogs)
{
if (set.getSize() == 0)//test if foundset is zero. if so ask if really want to print/preview
{
int val = JOptionPane.showConfirmDialog(
application.getMainApplicationFrame(),
Messages.getString("servoy.formPanel.error.noRecordsToPrint"), Messages.getString("servoy.general.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
if (val != JOptionPane.OK_OPTION)
{
return;
}
}
else if (!printCurrentRecordOnly)
{
int option = willingToPrint(set);
if (option == 2)
{
printCurrentRecordOnly = true;
}
else if (option == 1)
{
return;//cancel
}
}
}
if (printCurrentRecordOnly)
{
set = set.copyCurrentRecordFoundSet();
}
((FormManager)application.getFormManager()).showPreview(formController, set, zoomFactor, printerJob);
}
catch (Exception ex)
{
application.reportError(Messages.getString("servoy.formPanel.error.printPreview"), ex); //$NON-NLS-1$
}
}
/**
* @see com.servoy.j2db.IFormUIInternal#printXML(boolean)
*/
public String printXML(boolean printCurrentRecordOnly)
{
IApplication application = formController.getApplication();
IFoundSetInternal fs = formController.getFoundSet();
try
{
application.blockGUI(Messages.getString("servoy.formPanel.status.xmlPrinting")); //$NON-NLS-1$
if (printCurrentRecordOnly)
{
fs = fs.copyCurrentRecordFoundSet();
}
FormPreviewPanel fpp = new FormPreviewPanel(application, formController, fs);
fpp.process();
StringWriter w = new StringWriter();
((PageList)fpp.getPageable()).toXML(w);
fpp.destroy();
return w.toString();
}
catch (Throwable ex)
{
application.reportError(Messages.getString("servoy.formPanel.error.printDocument"), ex); //$NON-NLS-1$
}
finally
{
application.releaseGUI();
}
return null;
}
public String getId()
{
return (String)getClientProperty("Id"); //$NON-NLS-1$
}
public String getContainerName()
{
Container parent = getParent();
while (parent != null)
{
if (parent instanceof MainPanel)
{
return getPanelName((MainPanel)parent);
}
if (parent instanceof Window)
{
// in case of window plugin showing a popup form, we should return here the window that generated the popup form, just as in WC or for tabpanels
return findContainerNameInOwners((Window)parent);
}
parent = parent.getParent();
}
return null;
}
protected String getPanelName(MainPanel panel)
{
String name = panel.getContainerName();
if (name == null) name = IApplication.APP_WINDOW_NAME; // main container name is null for main app. window
return name;
}
protected String findContainerNameInOwners(Window win)
{
Window owner = win.getOwner();
if (owner == null)
{
Container tmp = win.getParent();
if (tmp instanceof Window) owner = (Window)tmp;
}
if (owner != null && owner != win)
{
// search for main panels in children
ConcurrentLinkedQueue<Component> childrenToVisit = new ConcurrentLinkedQueue<Component>();
childrenToVisit.add(owner);
Component child;
while ((child = childrenToVisit.poll()) != null)
{
if (child instanceof MainPanel)
{
return getPanelName((MainPanel)child);
}
if (child instanceof Container) childrenToVisit.addAll(Arrays.asList(((Container)child).getComponents()));
}
findContainerNameInOwners(owner);
}
return null;
}
/**
* @see com.servoy.j2db.IFormUIInternal#isFormInWindow()
*/
public boolean isFormInWindow()
{
Container parent = getParent();
while (parent != null)
{
if (parent instanceof FormDialog)
{
return parent.isVisible();
}
parent = parent.getParent();
}
return false;
}
/**
* @see java.awt.Component#toString()
*/
@Override
public String toString()
{
return "Form:" + getController().getName() + "," + super.toString(); //$NON-NLS-1$ //$NON-NLS-2$
}
public boolean isTraversalPolicyEnabled()
{
if (view instanceof ListView)
{
Component editor = ((ListView)view).getEditorComponent();
if (editor instanceof DataRenderer) return ((DataRenderer)editor).isTraversalPolicyEnabled();
}
return true;
}
private boolean isPartOfSlider(Component c)
{
if (c == null) return false;
if (c instanceof Slider) return true;
if (c.getParent() == null) return false;
if (c.getParent() instanceof Slider) return true;
return false;
}
private boolean isPartOfTabPanel(Component c)
{
if (c == null) return false;
if (c instanceof SpecialTabPanel) return true;
if (c.getParent() == null) return false;
if (c.getParent() instanceof SpecialTabPanel) return true;
return false;
}
public void prepareForSave(boolean looseFocus)
{
final Component currentFocusHolder = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
Component component = currentFocusHolder;
if (component instanceof JRootPane || component instanceof JFrame)
{
// do not give focus to swing form as will transfer it to first field
//component = this;
}
else while (component != null && !(component instanceof Window) && !(component instanceof IView) && !isPartOfSlider(component) &&
!isPartOfTabPanel(component))
{
component = component.getParent();
}
if (component != null && currentFocusHolder != component && !(component instanceof TableView) &&
!(component instanceof ListView && !((ListView)component).isEditing()))
{
// this used to be in invokelater, however reverted the change because it interfered with js focus calls
component.requestFocus();
}
}
public boolean isTransferFocusBackwards()
{
return transferFocusBackwards;
}
public void setTransferFocusBackwards(boolean transferBackwards)
{
this.transferFocusBackwards = transferBackwards;
}
private class GoOutOfSwingFormAction extends AbstractAction
{
private final boolean moveBackward;
public GoOutOfSwingFormAction(boolean moveBackward)
{
this.moveBackward = moveBackward;
}
public void actionPerformed(ActionEvent e)
{
Container formDirectParent = SwingForm.this.getParent();
boolean solved = false;
if (formDirectParent instanceof FormLookupPanel)
{
Component lastSpecialTabPanel = null;
SwingForm sf = null;
Component lastTabPanelAlike = null;
do
{
lastTabPanelAlike = formDirectParent.getParent();
lastSpecialTabPanel = lastTabPanelAlike.getParent();
Component parent = lastSpecialTabPanel.getParent();
while ((parent != null) && !(parent instanceof SwingForm))
parent = parent.getParent();
sf = (SwingForm)parent;
formDirectParent = sf.getParent();
}
while ((formDirectParent instanceof FormLookupPanel) &&
((lastSpecialTabPanel.equals(sf.getLastFocusableField()) && !moveBackward) || (lastSpecialTabPanel.equals(sf.getFirstFocusableField()) && moveBackward)));
((ISupportFocusTransfer)lastSpecialTabPanel).setTransferFocusBackwards(moveBackward);
if (lastTabPanelAlike instanceof SplitPane && SwingForm.this.getParent().equals(((SplitPane)lastTabPanelAlike).getLeftComponent()))
{
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(((SplitPane)lastTabPanelAlike).getRightComponent());
}
else if (moveBackward && lastTabPanelAlike instanceof JTabbedPane)
{
// if it moves backwards and it is a JTabbedPane then transfer the focus
// to the tab itself so that the tab of the tabpanel gets the focus
lastTabPanelAlike.requestFocus();
}
else KeyboardFocusManager.getCurrentKeyboardFocusManager().upFocusCycle(lastTabPanelAlike);
solved = true;
}
if (!solved)
{
SwingForm.this.setTransferFocusBackwards(moveBackward);
KeyboardFocusManager.getCurrentKeyboardFocusManager().upFocusCycle();
}
}
}
public boolean showYesNoQuestionDialog(IApplication application, String message, String title)
{
// create custom Yes/No buttons to avoid bug 129045 (ENTER from this dialog closing and showing the dialog again
// because the dialog closes on ENTER press and it is reopened on ENTER release) - reproducible with Servoy Developer 3.5.7_05-build 520 / Java version 1.5.0_11-b03 (Windows XP)
Component parentComponent = ((ISmartClientApplication)application).getMainApplicationFrame();
Locale l = parentComponent.getLocale();
JButton buttonYes = getNoDoClickJButton(UIManager.getString("OptionPane.yesButtonText", l), getMnemonic("OptionPane.yesButtonMnemonic", l)); //$NON-NLS-1$ //$NON-NLS-2$
JButton buttonNo = getNoDoClickJButton(UIManager.getString("OptionPane.noButtonText", l), getMnemonic("OptionPane.noButtonMnemonic", l)); //$NON-NLS-1$ //$NON-NLS-2$
final JOptionPane pane = new JOptionPane(message, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION, null, new Object[] { buttonYes, buttonNo },
buttonYes);
Font buttonFont = (Font)UIManager.get("OptionPane.buttonFont", parentComponent.getLocale()); //$NON-NLS-1$
if (buttonFont != null)
{
buttonYes.setFont(buttonFont);
buttonNo.setFont(buttonFont);
}
int threshhold = UIManager.getInt("OptionPane.buttonClickThreshhold", parentComponent.getLocale()); //$NON-NLS-1$
buttonYes.setMultiClickThreshhold(threshhold);
buttonNo.setMultiClickThreshhold(threshhold);
ActionListener selectButtonActionListener = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
pane.setValue(e.getSource());
}
};
buttonYes.addActionListener(selectButtonActionListener);
buttonNo.addActionListener(selectButtonActionListener);
pane.setInitialValue(buttonYes);
pane.setComponentOrientation(((parentComponent == null) ? JOptionPane.getRootFrame() : parentComponent).getComponentOrientation());
JDialog dialog = pane.createDialog(parentComponent, title);
pane.selectInitialValue();
dialog.setVisible(true);
dialog.dispose();
return pane.getValue() == buttonYes;
}
private int getMnemonic(String key, Locale l)
{
String value = (String)UIManager.get(key, l);
if (value == null)
{
return 0;
}
try
{
return Integer.parseInt(value);
}
catch (NumberFormatException nfe)
{
}
return 0;
}
private JButton getNoDoClickJButton(String text, int mnemonic)
{
KeyReleaseActionJButton b = new KeyReleaseActionJButton();
b.setText(text);
b.setMnemonic(mnemonic);
b.setName("OptionPane.button"); //$NON-NLS-1$
return b;
}
private JComponent realViewPort = null;
private JComponent realHeader = null;
private JComponent realTitleHeader = null;
private JComponent realFooter = null;
private JComponent realLeadingGrandSummary = null;
private JComponent realTrailingGrandSummary = null;
private final WeakHashMap<DesignModeCallbacks, SelectionHandler> designModeSelectionHandlers = new WeakHashMap<DesignModeCallbacks, SwingForm.SelectionHandler>();
/**
* @see com.servoy.j2db.IFormUIInternal#setDesignMode(boolean)
*/
public void setDesignMode(DesignModeCallbacks callback)
{
if (callback != null && realViewPort == null)
{
JLayeredPane pane = new JLayeredPane();
pane.setLayout(new LayeredPaneLayout());
realViewPort = (JComponent)getViewport().getView();
pane.setPreferredSize(realViewPort.getPreferredSize());
pane.setSize(realViewPort.getSize());
pane.add(realViewPort, new Integer(1));
SelectionHandler sh = designModeSelectionHandlers.get(callback);
if (sh == null)
{
sh = new SelectionHandler();
designModeSelectionHandlers.put(callback, sh);
}
final DesignPanel panel = new DesignPanel(DesignPanel.VIEW_TYPE.VIEWPORT, realViewPort, callback, formController, sh);
pane.add(panel, new Integer(2));
setViewportView(pane);
if (header != null)
{
realHeader = header;
DesignPanel designPanel = new DesignPanel(DesignPanel.VIEW_TYPE.HEADER, realHeader, callback, formController, sh);
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new LayeredPaneLayout());
layer.setPreferredSize(realHeader.getPreferredSize());
layer.setSize(realHeader.getSize());
layer.add(realHeader, new Integer(1));
layer.add(designPanel, new Integer(2));
setHeader(layer);
}
if (titleHeader != null)
{
realTitleHeader = titleHeader;
DesignPanel designPanel = new DesignPanel(DesignPanel.VIEW_TYPE.TITLE_HEADER, realTitleHeader, callback, formController, sh);
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new LayeredPaneLayout());
layer.setPreferredSize(realTitleHeader.getPreferredSize());
layer.setSize(realTitleHeader.getSize());
layer.add(realTitleHeader, new Integer(1));
layer.add(designPanel, new Integer(2));
setTitleHeader(layer);
}
if (footer != null)
{
realFooter = footer;
DesignPanel designPanel = new DesignPanel(DesignPanel.VIEW_TYPE.FOOTER, realFooter, callback, formController, sh);
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new LayeredPaneLayout());
layer.setPreferredSize(realFooter.getPreferredSize());
layer.setSize(realFooter.getSize());
layer.add(realFooter, new Integer(1));
layer.add(designPanel, new Integer(2));
setFooter(layer);
}
if (leadingGrandSummary != null)
{
realLeadingGrandSummary = leadingGrandSummary;
DesignPanel designPanel = new DesignPanel(DesignPanel.VIEW_TYPE.LEADING_GRAND_SUMMARY, realLeadingGrandSummary, callback, formController, sh);
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new LayeredPaneLayout());
layer.setPreferredSize(realLeadingGrandSummary.getPreferredSize());
layer.setSize(realLeadingGrandSummary.getSize());
layer.add(realLeadingGrandSummary, new Integer(1));
layer.add(designPanel, new Integer(2));
setLeadingGrandSummary(layer);
}
if (trailingGrandSummary != null)
{
realTrailingGrandSummary = trailingGrandSummary;
DesignPanel designPanel = new DesignPanel(DesignPanel.VIEW_TYPE.TRAILING_GRAND_SUMMARY, realTrailingGrandSummary, callback, formController, sh);
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new LayeredPaneLayout());
layer.setPreferredSize(realTrailingGrandSummary.getPreferredSize());
layer.setSize(realTrailingGrandSummary.getSize());
layer.add(realTrailingGrandSummary, new Integer(1));
layer.add(designPanel, new Integer(2));
setTrailingGrandSummary(layer);
}
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
panel.requestFocus();
}
});
}
else if (realViewPort != null)
{
setViewportView(realViewPort);
realViewPort = null;
if (realHeader != null)
{
setHeader(realHeader);
realHeader = null;
}
if (realTitleHeader != null)
{
setTitleHeader(realTitleHeader);
realTitleHeader = null;
}
if (realFooter != null)
{
setFooter(realFooter);
realFooter = null;
}
if (realLeadingGrandSummary != null)
{
setLeadingGrandSummary(realLeadingGrandSummary);
realLeadingGrandSummary = null;
}
if (realTrailingGrandSummary != null)
{
setTrailingGrandSummary(realTrailingGrandSummary);
realTrailingGrandSummary = null;
}
}
validate();
repaint();
// if (west != null) west.setEnabled(realViewPort == null);
}
public boolean isDesignMode()
{
return realViewPort != null;
}
/**
* @see com.servoy.j2db.IFormUIInternal#uiRecreated()
*/
public void uiRecreated()
{
// make sure the complete ui is validated (repainted)
validate();
}
public int getFormWidth()
{
return getSize().width;
}
public int getPartHeight(int partType)
{
if (formController.getDataRenderers() != null && formController.getDataRenderers().length > partType)
{
Component renderer = (Component)formController.getDataRenderers()[partType];
if (renderer != null)
{
return renderer.getHeight();
}
}
return 0;
}
@Override
public void paint(Graphics g)
{
// revert css3 features
// if (!formController.getForm().getTransparent() && bgColor != null)
// {
// Color tmp = g.getColor();
// // paint background color first, form is transparent
// g.setColor(bgColor);
// g.fillRect(0, 0, getWidth(), getHeight());
//
// g.setColor(tmp);
// }
// ImageLoader.paintImage(g, formController.getFormStyle(), formController.getApplication(), getSize());
super.paint(g);
}
public boolean hasBackgroundImage()
{
return (formController != null && formController.getFormStyle() != null && formController.getFormStyle().hasAttribute(
CSS.Attribute.BACKGROUND_IMAGE.toString()));
}
private static class LayeredPaneLayout implements LayoutManager2
{
/**
* @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object)
*/
public void addLayoutComponent(Component comp, Object constraints)
{
}
/**
* @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
*/
public float getLayoutAlignmentX(Container target)
{
return 0;
}
/**
* @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
*/
public float getLayoutAlignmentY(Container target)
{
return 0;
}
/**
* @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
*/
public void invalidateLayout(Container target)
{
}
/**
* @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
*/
public Dimension maximumLayoutSize(Container target)
{
return target.getSize();
}
/**
* @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
*/
public void addLayoutComponent(String name, Component comp)
{
}
/**
* @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
*/
public void layoutContainer(Container parent)
{
Dimension size = parent.getSize();
Component[] components = parent.getComponents();
for (Component component : components)
{
component.setBounds(0, 0, size.width, size.height);
}
}
/**
* @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
*/
public Dimension minimumLayoutSize(Container parent)
{
return new Dimension(0, 0);
}
/**
* @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
*/
public Dimension preferredLayoutSize(Container parent)
{
return parent.getPreferredSize();
}
/**
* @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
*/
public void removeLayoutComponent(Component comp)
{
}
}
private static class DesignPanel extends JPanel implements MouseListener, MouseMotionListener, AncestorListener
{
enum VIEW_TYPE
{
VIEWPORT, HEADER, TITLE_HEADER, FOOTER, LEADING_GRAND_SUMMARY, TRAILING_GRAND_SUMMARY
}
private final VIEW_TYPE viewType;
private final JComponent realViewPort;
private int dragMode;
private Point lastMousePosition;
private Point lassoPosition;
private final DesignModeCallbacks callback;
private final FormController controller;
private boolean resized;
private Object canResize;
private boolean moved;
private Object canMove;
private final SelectionHandler selectionHandler;
private final ComponentListener componentListener = new ComponentListener()
{
public void componentShown(ComponentEvent e)
{
}
public void componentResized(ComponentEvent e)
{
componentMoved(e);
}
public void componentMoved(ComponentEvent e)
{
Map<JComponent, int[][]> selection = selectionHandler.getSelection(DesignPanel.this);
if (selection.containsKey(e.getComponent()))
{
addSelectedComponent(e.getComponent(), e.getComponent().getBounds());
DesignPanel.this.repaint();
}
}
public void componentHidden(ComponentEvent e)
{
Map<JComponent, int[][]> selection = selectionHandler.getSelection(DesignPanel.this);
if (selection.containsKey(e.getComponent()))
{
selection.remove(e.getComponent());
DesignPanel.this.repaint();
}
}
};
public DesignPanel(VIEW_TYPE viewType, JComponent realViewPort, DesignModeCallbacks callback, FormController controller,
SelectionHandler selectionHandler)
{
this.viewType = viewType;
this.realViewPort = realViewPort;
this.callback = callback;
this.controller = controller;
this.selectionHandler = selectionHandler;
addMouseListener(this);
addMouseMotionListener(this);
addAncestorListener(this);
setFocusable(true);
setOpaque(false);
setPreferredSize(realViewPort.getPreferredSize());
setSize(realViewPort.getSize());
DesignPanel selectedDesignPanel = selectionHandler.getSelectedPanel();
if (selectedDesignPanel != null && selectedDesignPanel.getViewType() == viewType && selectedDesignPanel.getFormController() == controller)
{
selectionHandler.setSelectedPanel(this);
Map<JComponent, int[][]> selectionMap = DesignPanel.this.selectionHandler.getSelection(DesignPanel.this);
JComponent[] selectedComps = selectionMap.keySet().toArray(new JComponent[selectionMap.size()]);
String selectedCompName;
Component realSelectedComp;
for (JComponent selectedComp : selectedComps)
{
selectionMap.remove(selectedComp);
if ((selectedCompName = selectedComp.getName()) != null)
{
realSelectedComp = findComponentByName(selectedCompName, realViewPort);
if (realSelectedComp != null)
{
addSelectedComponent(realSelectedComp, realSelectedComp.getBounds());
}
}
}
}
attachComponentListener(realViewPort);
}
VIEW_TYPE getViewType()
{
return viewType;
}
FormController getFormController()
{
return controller;
}
private Component findComponentByName(String name, Component container)
{
if (name.equals(container.getName())) return container;
if (container instanceof Container)
{
Component namedComp = null;
for (Component c : ((Container)container).getComponents())
{
namedComp = findComponentByName(name, c);
if (namedComp != null) return namedComp;
}
}
return null;
}
private void attachComponentListener(Container comp)
{
Component[] components = comp.getComponents();
for (Component component : components)
{
if (component instanceof IDisplay || component instanceof ScriptLabel || component instanceof ScriptButton)
{
component.addComponentListener(componentListener);
}
else if (component instanceof Container)
{
attachComponentListener((Container)component);
}
}
}
public void mousePressed(MouseEvent e)
{
requestFocus();
dragMode = -1;
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelectionForChange(this);
if (selectedComponents.size() == 1)
{
int[][] positions = selectedComponents.values().iterator().next();
if (positions != null)
{
int x = e.getX();
int y = e.getY();
for (int i = 0; i < positions.length; i++)
{
int[] position = positions[i];
if (position[0] < x && x < (position[0] + 6))
{
if (position[1] < y && y < (position[1] + 6))
{
dragMode = i;
return;
}
}
}
}
}
boolean changed = false;
lastMousePosition = e.getPoint();
JComponent selectedComponent = (JComponent)SwingUtilities.getDeepestComponentAt(realViewPort, e.getX(), e.getY());
Container panel = SwingUtilities.getAncestorOfClass(ITabPanel.class, selectedComponent);
while (panel != null)
{
if (SwingUtilities.isDescendingFrom(panel, realViewPort))
{
selectedComponent = (JComponent)panel;
panel = SwingUtilities.getAncestorOfClass(ITabPanel.class, selectedComponent);
}
else
{
panel = null;
}
}
if (selectedComponent == realViewPort || selectedComponent instanceof DataRenderer)
{
changed = selectedComponents.size() > 0;
selectedComponents.clear();
}
else
{
while (selectedComponent.getParent() != realViewPort && !(selectedComponent.getParent() instanceof DataRenderer))
{
selectedComponent = (JComponent)selectedComponent.getParent();
}
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK && selectedComponents.containsKey(selectedComponent))
{
changed = selectedComponents.remove(selectedComponent) != null;
selectedComponent = null;
}
else
{
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != InputEvent.CTRL_DOWN_MASK && !selectedComponents.containsKey(selectedComponent))
{
changed = selectedComponents.size() > 0;
selectedComponents.clear();
}
changed = addSelectedComponent(selectedComponent, selectedComponent.getBounds()) || changed;
}
}
if (changed)
{
Object ret = callback.executeOnSelect(getJSEvent(e, EventType.action));
if (selectedComponent != null && ret instanceof Boolean && !((Boolean)ret).booleanValue())
{
selectedComponents.remove(selectedComponent);
}
}
repaint();
}
/**
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(MouseEvent e)
{
if (lastMousePosition != null && lassoPosition != null)
{
int x = Math.min(lassoPosition.x, lastMousePosition.x);
int y = Math.min(lassoPosition.y, lastMousePosition.y);
int height = Math.abs(lassoPosition.y - lastMousePosition.y);
int width = Math.abs(lassoPosition.x - lastMousePosition.x);
Rectangle rect = new Rectangle(x, y, width, height);
List<JComponent> changed = calculateSelection(realViewPort, rect);
if (changed.size() > 0)
{
Object ret = callback.executeOnSelect(getJSEvent(e, EventType.action));
if (ret instanceof Boolean && !((Boolean)ret).booleanValue())
{
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelectionForChange(this);
selectedComponents.keySet().removeAll(changed);
}
}
}
if (moved)
{
callback.executeOnDrop(getJSEvent(e, EventType.onDrop));
}
if (resized)
{
callback.executeOnResize(getJSEvent(e, EventType.onDrop));
}
if (SwingUtilities.isRightMouseButton(e)) callback.executeOnRightClick(getJSEvent(e, EventType.rightClick));
else if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) callback.executeOnDblClick(getJSEvent(e, EventType.doubleClick));
dragMode = -1;
lastMousePosition = null;
lassoPosition = null;
canMove = null;
moved = false;
canResize = null;
resized = false;
setCursor(Cursor.getDefaultCursor());
repaint();
}
/**
* @param e
*/
private JSEvent getJSEvent(MouseEvent e, EventType type)
{
JSEvent event = new JSEvent();
event.setFormName(controller.getName());
event.setType(type);
event.setModifiers(e.getModifiers());
event.setLocation(e.getPoint());
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelectionForChange(this);
List<Object> selection = new ArrayList<Object>();
for (JComponent component : selectedComponents.keySet())
{
if (component instanceof IScriptableProvider)
{
selection.add(0, ((IScriptableProvider)component).getScriptObject());
}
else
{
selection.add(0, component);
}
}
event.setData(selection.toArray());
//event.setSource(e)
return event;
}
/**
* @param rect
*/
private List<JComponent> calculateSelection(JComponent parent, Rectangle rect)
{
List<JComponent> changed = new ArrayList<JComponent>();
Component[] comps = parent.getComponents();
for (Component component : comps)
{
if (component instanceof DataRenderer)
{
changed.addAll(calculateSelection((JComponent)component, rect));
}
else if (rect.contains(component.getBounds()))
{
if (addSelectedComponent(component, component.getBounds()))
{
changed.add((JComponent)component);
}
}
}
return changed;
}
/**
* @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
*/
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelection(this);
if (selectedComponents.size() > 0)
{
Iterator<Entry<JComponent, int[][]>> iterator = selectedComponents.entrySet().iterator();
while (iterator.hasNext())
{
Entry<JComponent, int[][]> entry = iterator.next();
JComponent selectedComponent = entry.getKey();
int[][] positions = entry.getValue();
g.setColor(Color.black);
Rectangle bounds = selectedComponent.getBounds();
g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
for (int[] position : positions)
{
if (position[0] == -1) continue;
g.setColor(Color.black);
g.fillRect(position[0] + 1, position[1] + 1, 4, 4);
g.setColor(Color.white);
g.drawRect(position[0], position[1], 5, 5);
}
}
}
if (lassoPosition != null && lastMousePosition != null)
{
g.setColor(Color.black);
Stroke s = new BasicStroke(1.0f, // Width
BasicStroke.CAP_SQUARE, // End cap
BasicStroke.JOIN_ROUND, // Join style
0.0f, // Miter limit
new float[] { 3.0f, 3.0f }, // Dash pattern
0.0f); // Dash phase
((Graphics2D)g).setStroke(s);
int x = Math.min(lassoPosition.x, lastMousePosition.x);
int y = Math.min(lassoPosition.y, lastMousePosition.y);
int height = Math.abs(lassoPosition.y - lastMousePosition.y);
int width = Math.abs(lassoPosition.x - lastMousePosition.x);
g.drawRect(x, y, width, height);
}
}
/**
* @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
*/
public void mouseDragged(MouseEvent e)
{
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelectionForChange(this);
if (dragMode != -1 && selectedComponents.size() == 1)
{
if (!resized)
{
if (canResize == null)
{
canResize = callback.executeOnDrag(getJSEvent(e, EventType.onDrag));
}
if ((canResize instanceof Boolean && !((Boolean)canResize).booleanValue()) ||
(canResize instanceof Number && ((Number)canResize).intValue() == DRAGNDROP.NONE)) return; //drag stopped
}
JComponent selectedComponent = selectedComponents.keySet().iterator().next();
Rectangle current = selectedComponent.getBounds();
Rectangle bounds = new Rectangle(current);
switch (dragMode)
{
case 0 :
bounds.x = e.getX();
bounds.y = e.getY();
bounds.width = current.width - (e.getX() - current.x);
bounds.height = current.height - (e.getY() - current.y);
break;
case 1 :
bounds.x = e.getX();
bounds.width = current.width - (e.getX() - current.x);
break;
case 2 :
bounds.x = e.getX();
bounds.width = current.width - (e.getX() - current.x);
bounds.height = e.getY() - current.y;
break;
case 3 :
bounds.y = e.getY();
bounds.height = current.height - (e.getY() - current.y);
break;
case 4 :
bounds.height = e.getY() - current.y;
break;
case 5 :
bounds.y = e.getY();
bounds.width = e.getX() - current.x;
bounds.height = current.height - (e.getY() - current.y);
break;
case 6 :
bounds.width = e.getX() - current.x;
break;
case 7 :
bounds.width = e.getX() - current.x;
bounds.height = e.getY() - current.y;
}
if (bounds.x < 1) bounds.x = 1;
if (bounds.y < 1) bounds.y = 1;
if (bounds.height < 1) bounds.height = 4;
if (bounds.width < 1) bounds.width = 4;
resized = true;
addSelectedComponent(selectedComponent, bounds);
}
else if (lastMousePosition != null)
{
if (selectedComponents.size() > 0)
{
if (e.getY() >= 0 && e.getX() >= 0)
{
if (!moved && canMove == null)
{
canMove = callback.executeOnDrag(getJSEvent(e, EventType.onDrag));
}
if (!(canMove instanceof Boolean && !((Boolean)canMove).booleanValue()) &&
!(canMove instanceof Number && ((Number)canMove).intValue() == DRAGNDROP.NONE))
{
Map<JComponent, Rectangle> toUpdate = new HashMap<JComponent, Rectangle>(selectedComponents.size());
Iterator<JComponent> iterator = selectedComponents.keySet().iterator();
int panelWidth = getWidth();
int panelHeight = getHeight();
while (iterator.hasNext())
{
JComponent selectedComponent = iterator.next();
Rectangle current = selectedComponent.getBounds();
int x = current.x + (e.getX() - lastMousePosition.x);
int y = current.y + (e.getY() - lastMousePosition.y);
if (x < 0 || y < 0 || (x + current.width) > panelWidth || (y + current.height) > panelHeight)
{
toUpdate.clear();
break;
}
current.x = x;
current.y = y;
toUpdate.put(selectedComponent, current);
}
if (toUpdate.size() > 0)
{
Iterator<Entry<JComponent, Rectangle>> it = toUpdate.entrySet().iterator();
while (it.hasNext())
{
Entry<JComponent, Rectangle> entry = it.next();
addSelectedComponent(entry.getKey(), entry.getValue());
}
moved = true;
setCursor(new Cursor(Cursor.MOVE_CURSOR));
}
else
{
setCursor(Cursor.getDefaultCursor());
}
}
}
}
else
{
if (lassoPosition == null)
{
lassoPosition = lastMousePosition;
}
}
lastMousePosition = e.getPoint();
}
repaint();
}
private boolean addSelectedComponent(Component component, Rectangle bounds)
{
if (component != null && !component.isVisible()) return false;
Object clientdesign_handles = null;
if (component instanceof IScriptableProvider && ((IScriptableProvider)component).getScriptObject() instanceof IRuntimeComponent)
{
IRuntimeComponent sbmc = (IRuntimeComponent)((IScriptableProvider)component).getScriptObject();
if (sbmc.getName() == null) return false; //skip, elements with no name are not usable in CD
clientdesign_handles = sbmc.getClientProperty(CLIENTDESIGN.HANDLES);
Object clientdesign_selectable = sbmc.getClientProperty(CLIENTDESIGN.SELECTABLE);
if (clientdesign_selectable != null && !Utils.getAsBoolean(clientdesign_selectable)) return false; //skip
}
Set<String> handles = null;
if (clientdesign_handles instanceof Object[])
{
handles = new HashSet<String>();
for (int i = 0; i < ((Object[])clientdesign_handles).length; i++)
{
String val = ((Object[])clientdesign_handles)[i].toString();
handles.add(Utils.stringReplace(val, "'", ""));
}
}
component.setBounds(bounds);
int[][] positions = new int[8][2];
if (handles == null || handles.contains("tl"))
{
positions[0][0] = bounds.x - 2;
positions[0][1] = bounds.y - 2;
}
else
{
positions[0][0] = -1;
positions[0][1] = -1;
}
if (handles == null || handles.contains("l"))
{
positions[1][0] = bounds.x - 2;
positions[1][1] = bounds.y + bounds.height / 2 - 3;
}
else
{
positions[1][0] = -1;
positions[1][1] = -1;
}
if (handles == null || handles.contains("bl"))
{
positions[2][0] = bounds.x - 2;
positions[2][1] = bounds.y + bounds.height - 3;
}
else
{
positions[2][0] = -1;
positions[2][1] = -1;
}
if (handles == null || handles.contains("t"))
{
positions[3][0] = bounds.x + bounds.width / 2 - 3;
positions[3][1] = bounds.y - 3;
}
else
{
positions[3][0] = -1;
positions[3][1] = -1;
}
if (handles == null || handles.contains("b"))
{
positions[4][0] = bounds.x + bounds.width / 2 - 3;
positions[4][1] = bounds.y + bounds.height - 3;
}
else
{
positions[4][0] = -1;
positions[4][1] = -1;
}
if (handles == null || handles.contains("tr"))
{
positions[5][0] = bounds.x + bounds.width - 3;
positions[5][1] = bounds.y - 2;
}
else
{
positions[5][0] = -1;
positions[5][1] = -1;
}
if (handles == null || handles.contains("r"))
{
positions[6][0] = bounds.x + bounds.width - 3;
positions[6][1] = bounds.y + bounds.height / 2 - 3;
}
else
{
positions[6][0] = -1;
positions[6][1] = -1;
}
if (handles == null || handles.contains("br"))
{
positions[7][0] = bounds.x + bounds.width - 3;
positions[7][1] = bounds.y + bounds.height - 3;
}
else
{
positions[7][0] = -1;
positions[7][1] = -1;
}
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelectionForChange(this);
return selectedComponents.put((JComponent)component, positions) == null;
}
public void mouseMoved(MouseEvent e)
{
Map<JComponent, int[][]> selectedComponents = selectionHandler.getSelection(this);
if (selectedComponents.size() == 1)
{
int[][] positions = selectedComponents.values().iterator().next();
int x = e.getX();
int y = e.getY();
for (int i = 0; i < positions.length; i++)
{
int[] position = positions[i];
if (position[0] < x && x < (position[0] + 6))
{
if (position[1] < y && y < (position[1] + 6))
{
switch (i)
{
case 0 :
setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR));
break;
case 1 :
setCursor(new Cursor(Cursor.E_RESIZE_CURSOR));
break;
case 2 :
setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
break;
case 3 :
setCursor(new Cursor(Cursor.N_RESIZE_CURSOR));
break;
case 4 :
setCursor(new Cursor(Cursor.S_RESIZE_CURSOR));
break;
case 5 :
setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR));
break;
case 6 :
setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
break;
case 7 :
setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
break;
}
return;
}
}
}
}
setCursor(Cursor.getDefaultCursor());
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
/**
* @see javax.swing.event.AncestorListener#ancestorAdded(javax.swing.event.AncestorEvent)
*/
public void ancestorAdded(AncestorEvent event)
{
}
/**
* @see javax.swing.event.AncestorListener#ancestorMoved(javax.swing.event.AncestorEvent)
*/
public void ancestorMoved(AncestorEvent event)
{
}
/**
* @see javax.swing.event.AncestorListener#ancestorRemoved(javax.swing.event.AncestorEvent)
*/
public void ancestorRemoved(AncestorEvent event)
{
removeComponentListener(realViewPort);
}
private void removeComponentListener(Container comp)
{
Component[] components = comp.getComponents();
for (Component component : components)
{
if (component instanceof IDisplay || component instanceof ScriptLabel || component instanceof ScriptButton)
{
component.removeComponentListener(componentListener);
}
else if (component instanceof Container)
{
removeComponentListener((Container)component);
}
}
}
}
private static class SelectionHandler
{
private final Map<JComponent, int[][]> selectedComponents = new HashMap<JComponent, int[][]>();
private DesignPanel selectedPanel = null;
public Map<JComponent, int[][]> getSelection(DesignPanel panel)
{
if (selectedPanel == panel)
{
return selectedComponents;
}
return Collections.emptyMap();
}
public Map<JComponent, int[][]> getSelectionForChange(DesignPanel panel)
{
if (selectedPanel != panel && selectedComponents.size() > 0)
{
selectedComponents.clear();
selectedPanel.repaint();
}
selectedPanel = panel;
return selectedComponents;
}
DesignPanel getSelectedPanel()
{
return selectedPanel;
}
void setSelectedPanel(DesignPanel designPanel)
{
selectedPanel = designPanel;
}
}
@Override
public void changeFocusIfInvalid(List<Runnable> invokeLaterRunnables)
{
final Window window = SwingUtilities.getWindowAncestor(this);
if (window != null)
{
Runnable r = new Runnable()
{
public void run()
{
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (!(focusOwner != null && focusOwner.isShowing() && focusOwner.isFocusable() && focusOwner.isEnabled()))
{
if (window.isShowing() && window.isFocusable() && window.isEnabled())
{
window.requestFocus();
}
}
}
};
invokeLaterRunnables.add(r);
}
}
}