IDEMPIERE-5570 Zk: Improve readability of code (#1675)
* IDEMPIERE-5570 Zk: Improve readability of code * IDEMPIERE-5570 Zk: Improve readability of code - Improve readability for org.adempiere.webui.apps package.
This commit is contained in:
parent
17f1957d70
commit
dff85c45de
|
@ -33,7 +33,7 @@ import org.compiere.util.Evaluator;
|
|||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Abstract model and controller for AD_Tab+AD_Field. UI part is implemented in sub class.
|
||||
* Abstract base class for header+details AD_Tabs UI for AD_Window.
|
||||
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
|
||||
* @author <a href="mailto:hengsin@gmail.com">Low Heng Sin</a>
|
||||
* @date Feb 25, 2007
|
||||
|
@ -41,12 +41,12 @@ import org.compiere.util.Util;
|
|||
*/
|
||||
public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabbox
|
||||
{
|
||||
/** Logger */
|
||||
/** Logger **/
|
||||
private static final CLogger log = CLogger.getCLogger (AbstractADTabbox.class);
|
||||
/** List of dependent Variables */
|
||||
/** List of variables/columnName that's reference by one or more gridTab logic expression **/
|
||||
private ArrayList<String> m_dependents = new ArrayList<String>();
|
||||
|
||||
/** AD tab panels associated to this tab box */
|
||||
/** List of {@link IADTabpanel} instance manage by this AbstractADTabbox instance **/
|
||||
protected List<IADTabpanel> tabPanelList = new ArrayList<IADTabpanel>();
|
||||
/** Parent part, the content part of AD Window **/
|
||||
protected AbstractADWindowContent adWindowPanel;
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.adempiere.webui.LayoutUtils;
|
|||
import org.adempiere.webui.adwindow.ADWindow;
|
||||
import org.adempiere.webui.component.Mask;
|
||||
import org.adempiere.webui.component.Window;
|
||||
import org.adempiere.webui.desktop.IDesktop;
|
||||
import org.adempiere.webui.editor.WTableDirEditor;
|
||||
import org.adempiere.webui.event.DialogEvents;
|
||||
import org.adempiere.webui.event.DrillEvent.DrillData;
|
||||
|
@ -86,7 +87,7 @@ import org.zkoss.zul.impl.InputElement;
|
|||
import com.lowagie.text.DocumentException;
|
||||
|
||||
/**
|
||||
* ZK Application Environment and utilities
|
||||
* Static application environment and utilities methods.
|
||||
*
|
||||
* @author Jorg Janke
|
||||
* @version $Id: AEnv.java,v 1.2 2006/07/30 00:51:27 jjanke Exp $
|
||||
|
@ -95,11 +96,11 @@ import com.lowagie.text.DocumentException;
|
|||
*/
|
||||
public final class AEnv
|
||||
{
|
||||
/** Environment context attribute for Locale **/
|
||||
public static final String LOCALE = Env.LOCALE;
|
||||
|
||||
/**
|
||||
* Show in the center of the screen.
|
||||
* (pack, set location and set visibility)
|
||||
* Show window in the center of screen.
|
||||
* @param window Window to position
|
||||
*/
|
||||
public static void showCenterScreen(Window window)
|
||||
|
@ -120,8 +121,7 @@ public final class AEnv
|
|||
} // showCenterScreen
|
||||
|
||||
/**
|
||||
* Show in the center of the screen.
|
||||
* (pack, set location and set visibility)
|
||||
* Set window position ({@link org.zkoss.zul.Window#setPosition(String)}) and show it.
|
||||
* @param window Window to position
|
||||
* @param position
|
||||
*/
|
||||
|
@ -131,8 +131,7 @@ public final class AEnv
|
|||
} // showScreen
|
||||
|
||||
/**
|
||||
* Position in center of the parent window.
|
||||
* (pack, set location and set visibility)
|
||||
* Position window in center of the parent window.
|
||||
* @param parent Parent Window
|
||||
* @param window Window to position
|
||||
*/
|
||||
|
@ -145,7 +144,7 @@ public final class AEnv
|
|||
/**
|
||||
* Get Mnemonic character from text.
|
||||
* @param text text with '&'
|
||||
* @return Mnemonic or 0
|
||||
* @return Mnemonic character or 0
|
||||
*/
|
||||
public static char getMnemonic (String text)
|
||||
{
|
||||
|
@ -159,7 +158,7 @@ public final class AEnv
|
|||
|
||||
|
||||
/*************************************************************************
|
||||
* Zoom
|
||||
* Zoom to AD Window by AD_Table_ID and Record_ID.
|
||||
* @param AD_Table_ID
|
||||
* @param Record_ID
|
||||
*/
|
||||
|
@ -178,10 +177,11 @@ public final class AEnv
|
|||
} // zoom
|
||||
|
||||
/*************************************************************************
|
||||
* Zoom
|
||||
* Zoom to AD Window by AD_Table_ID and Record_ID.
|
||||
* @param AD_Table_ID
|
||||
* @param Record_ID
|
||||
* @param query
|
||||
* @param query initial query for destination AD Window
|
||||
* @param windowNo
|
||||
*/
|
||||
public static void zoom (int AD_Table_ID, int Record_ID, MQuery query, int windowNo)
|
||||
{
|
||||
|
@ -192,21 +192,28 @@ public final class AEnv
|
|||
zoom(AD_Window_ID, query);
|
||||
} // zoom
|
||||
|
||||
/**
|
||||
* Call {@link #zoom(int, int, MQuery, int)}
|
||||
* @param AD_Table_ID
|
||||
* @param Record_ID
|
||||
* @param query
|
||||
*/
|
||||
public static void zoom (int AD_Table_ID, int Record_ID, MQuery query) {
|
||||
zoom (AD_Table_ID, Record_ID, query, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit System
|
||||
* Exit System.
|
||||
* @param status System exit status (usually 0 for no error)
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "11")
|
||||
public static void exit (int status)
|
||||
{
|
||||
Env.exitEnv(status);
|
||||
} // exit
|
||||
|
||||
/**
|
||||
* logout AD_Session
|
||||
* Logout AD_Session and clear {@link #windowCache}.
|
||||
*/
|
||||
public static void logout()
|
||||
{
|
||||
|
@ -228,13 +235,12 @@ public final class AEnv
|
|||
session.logout();
|
||||
|
||||
Env.setContext(Env.getCtx(), Env.AD_SESSION_ID, (String)null);
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Workflow Process Window
|
||||
* @param AD_Table_ID optional table
|
||||
* @param Record_ID optional record
|
||||
* Open Workflow Process Window for AD_Table_ID and Record_ID
|
||||
* @param AD_Table_ID
|
||||
* @param Record_ID
|
||||
*/
|
||||
public static void startWorkflowProcess (int AD_Table_ID, int Record_ID)
|
||||
{
|
||||
|
@ -253,28 +259,24 @@ public final class AEnv
|
|||
AEnv.zoom(s_workflow_Window_ID, query);
|
||||
} // startWorkflowProcess
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/** Workflow Window */
|
||||
/** Cache Workflow Window ID **/
|
||||
private static int s_workflow_Window_ID = 0;
|
||||
/** Logger */
|
||||
private static final CLogger log = CLogger.getCLogger(AEnv.class);
|
||||
|
||||
/** Window Cache */
|
||||
/** Register AD Window Cache **/
|
||||
private static Map<String, CCache<Integer,GridWindowVO>> windowCache = new HashMap<String, CCache<Integer,GridWindowVO>>();
|
||||
|
||||
/**
|
||||
* Get Window Model
|
||||
* Get VO for AD_Window
|
||||
*
|
||||
* @param WindowNo Window No
|
||||
* @param AD_Window_ID window
|
||||
* @param AD_Menu_ID menu
|
||||
* @return Model Window Value Obkect
|
||||
* @return {@link GridWindowVO} instance for AD_Window_ID
|
||||
*/
|
||||
public static GridWindowVO getMWindowVO (int WindowNo, int AD_Window_ID, int AD_Menu_ID)
|
||||
{
|
||||
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID);
|
||||
GridWindowVO mWindowVO = null;
|
||||
String sessionID = Env.getContext(Env.getCtx(), Env.AD_SESSION_ID);
|
||||
|
@ -299,6 +301,7 @@ public final class AEnv
|
|||
// Create Window Model on Client
|
||||
if (mWindowVO == null)
|
||||
{
|
||||
if (log.isLoggable(Level.CONFIG))
|
||||
log.config("create local");
|
||||
mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID, AD_Menu_ID);
|
||||
if (mWindowVO != null && Ini.isCacheWindow())
|
||||
|
@ -318,10 +321,9 @@ public final class AEnv
|
|||
if (mWindowVO == null)
|
||||
return null;
|
||||
|
||||
// Check (remote) context
|
||||
// Check context
|
||||
if (!mWindowVO.ctx.equals(Env.getCtx()))
|
||||
{
|
||||
// Remote Context is called by value, not reference
|
||||
// Add Window properties to context
|
||||
Enumeration<Object> keyEnum = mWindowVO.ctx.keys();
|
||||
while (keyEnum.hasMoreElements())
|
||||
|
@ -341,12 +343,13 @@ public final class AEnv
|
|||
} // getWindow
|
||||
|
||||
/**
|
||||
* Post Immediate
|
||||
* Post Immediate.
|
||||
* Call {@link Doc#manualPosting(int, int, int, int, boolean)}.
|
||||
* @param WindowNo window
|
||||
* @param AD_Table_ID Table ID of Document
|
||||
* @param AD_Client_ID Client ID of Document
|
||||
* @param Record_ID Record ID of this document
|
||||
* @param force force posting
|
||||
* @param Record_ID Record ID of Document
|
||||
* @param force force posting. if false, only post if (Processing='N' OR Processing IS NULL)
|
||||
* @return null if success, otherwise error
|
||||
*/
|
||||
public static String postImmediate (int WindowNo, int AD_Client_ID,
|
||||
|
@ -373,6 +376,13 @@ public final class AEnv
|
|||
CacheMgt.get().reset(tableName, Record_ID);
|
||||
} // cacheReset
|
||||
|
||||
/**
|
||||
* Refresh lookup
|
||||
* @param lookup
|
||||
* @param value
|
||||
* @param mandatory
|
||||
* @param shortList
|
||||
*/
|
||||
public static void actionRefresh(Lookup lookup, Object value, boolean mandatory, boolean shortList) // IDEMPIERE 90
|
||||
{
|
||||
if (lookup == null)
|
||||
|
@ -385,9 +395,9 @@ public final class AEnv
|
|||
lookup.fillComboBox(mandatory, true, false, false, shortList); // IDEMPIERE 90
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param lookup
|
||||
* @param value
|
||||
* zoom to AD Window
|
||||
* @param lookup lookup for zoom destination table
|
||||
* @param value record key
|
||||
*/
|
||||
public static void actionZoom(Lookup lookup, Object value)
|
||||
{
|
||||
|
@ -492,7 +502,7 @@ public final class AEnv
|
|||
}
|
||||
|
||||
/**
|
||||
* Zoom to a window with the provided window id and filters according to the
|
||||
* Zoom to AD window with the provided window id and filters according to the
|
||||
* query
|
||||
* @param AD_Window_ID Window on which to zoom
|
||||
* @param query Filter to be applied on the records.
|
||||
|
@ -503,17 +513,27 @@ public final class AEnv
|
|||
showZoomWindow(zoomId > 0 ? zoomId : AD_Window_ID, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #zoom(int, MQuery, int)}
|
||||
* @param AD_Window_ID
|
||||
* @param query
|
||||
*/
|
||||
public static void zoom(int AD_Window_ID, MQuery query) {
|
||||
zoom(AD_Window_ID, query, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show window in desktop.
|
||||
* Call {@link IDesktop#showWindow(Window)}.
|
||||
* @param win
|
||||
*/
|
||||
public static void showWindow(Window win)
|
||||
{
|
||||
SessionManager.getAppDesktop().showWindow(win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom
|
||||
* Zoom to AD Window with details from query
|
||||
* @param query query
|
||||
*/
|
||||
public static void zoom (MQuery query)
|
||||
|
@ -537,7 +557,7 @@ public final class AEnv
|
|||
* Get ImageIcon.
|
||||
*
|
||||
* @param fileNameInImageDir full file name in imgaes folder (e.g. Bean16.png)
|
||||
* @return image
|
||||
* @return image {@link URI}
|
||||
*/
|
||||
public static URI getImage(String fileNameInImageDir)
|
||||
{
|
||||
|
@ -555,8 +575,7 @@ public final class AEnv
|
|||
} // getImageIcon
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
* @return true if client browser is firefox 2+
|
||||
*/
|
||||
public static boolean isFirefox2() {
|
||||
Execution execution = Executions.getCurrent();
|
||||
|
@ -626,10 +645,9 @@ public final class AEnv
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param parent
|
||||
* @param child
|
||||
* @return boolean
|
||||
* @return true if parent == child or parent is ancestor of child.
|
||||
*/
|
||||
public static boolean contains(Component parent, Component child) {
|
||||
if (child == parent)
|
||||
|
@ -646,7 +664,7 @@ public final class AEnv
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Merge pdfList to outFile
|
||||
* @param pdfList
|
||||
* @param outFile
|
||||
* @throws IOException
|
||||
|
@ -687,7 +705,7 @@ public final class AEnv
|
|||
|
||||
/**
|
||||
* @param ctx
|
||||
* @return Language
|
||||
* @return {@link Language}
|
||||
*/
|
||||
public static Language getLanguage(Properties ctx) {
|
||||
return Env.getLocaleLanguage(ctx);
|
||||
|
@ -695,7 +713,7 @@ public final class AEnv
|
|||
|
||||
/**
|
||||
* @param ctx
|
||||
* @return Locale
|
||||
* @return {@link Locale}
|
||||
*/
|
||||
public static Locale getLocale(Properties ctx) {
|
||||
return Env.getLocale(ctx);
|
||||
|
@ -741,12 +759,19 @@ public final class AEnv
|
|||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #getDialogHeader(Properties, int, String)}
|
||||
* @param ctx
|
||||
* @param windowNo
|
||||
* @return dialog header
|
||||
*/
|
||||
public static String getDialogHeader(Properties ctx, int windowNo) {
|
||||
return getDialogHeader(ctx, windowNo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute synchronous task in UI thread.
|
||||
* Use {@link Executions#activate(Desktop)} and {@link Executions#deactivate(Desktop)} pair if current thread is not UI/Listener thread.
|
||||
* @param runnable
|
||||
*/
|
||||
public static void executeDesktopTask(final Runnable runnable) {
|
||||
|
@ -777,7 +802,7 @@ public final class AEnv
|
|||
|
||||
/**
|
||||
* Get current desktop
|
||||
* @return Desktop
|
||||
* @return {@link Desktop}
|
||||
*/
|
||||
public static Desktop getDesktop() {
|
||||
boolean inUIThread = Executions.getCurrent() != null;
|
||||
|
@ -793,6 +818,7 @@ public final class AEnv
|
|||
* @deprecated replace by ClientInfo.isMobile()
|
||||
* @return true if running on a tablet
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "11")
|
||||
public static boolean isTablet() {
|
||||
return ClientInfo.isMobile();
|
||||
}
|
||||
|
@ -822,6 +848,12 @@ public final class AEnv
|
|||
return adWindowID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client
|
||||
* @return {@link WTableDirEditor} for Language if client is with IsMultiLingualDocument=Y
|
||||
* @throws Exception
|
||||
*/
|
||||
public static WTableDirEditor getListDocumentLanguage (MClient client) throws Exception {
|
||||
WTableDirEditor fLanguageType = null;
|
||||
if (client.isMultiLingualDocument()){
|
||||
|
@ -834,6 +866,10 @@ public final class AEnv
|
|||
}
|
||||
|
||||
private static String m_ApplicationUrl = null;
|
||||
|
||||
/**
|
||||
* @return URL to access application from browser
|
||||
*/
|
||||
public static String getApplicationUrl() {
|
||||
String url = MSysConfig.getValue(MSysConfig.APPLICATION_URL, Env.getAD_Client_ID(Env.getCtx()));
|
||||
if (!Util.isEmpty(url) && !url.equals("USE_HARDCODED"))
|
||||
|
@ -851,20 +887,26 @@ public final class AEnv
|
|||
return m_ApplicationUrl;
|
||||
}
|
||||
|
||||
/** Return the link for direct access to the record using tableID */
|
||||
/**
|
||||
* @param po
|
||||
* @return URL link for direct access to the record using AD_Table_ID+Record_ID
|
||||
*/
|
||||
public static String getZoomUrlTableID(PO po)
|
||||
{
|
||||
return getApplicationUrl() + "?Action=Zoom&AD_Table_ID=" + po.get_Table_ID() + "&Record_ID=" + po.get_ID();
|
||||
}
|
||||
|
||||
/** Return the link for direct access to the record using tablename */
|
||||
/**
|
||||
* @param po
|
||||
* @return URL link for direct access to the record using TableName+Record_ID
|
||||
*/
|
||||
public static String getZoomUrlTableName(PO po)
|
||||
{
|
||||
return getApplicationUrl() + "?Action=Zoom&TableName" + po.get_TableName() + "&Record_ID=" + po.get_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Set attribute value to Boolean.TRUE if attribute doesn't exists in current execution yet.
|
||||
* @param attribute
|
||||
* @return true if attribute have been set for current executions
|
||||
*/
|
||||
|
@ -878,17 +920,22 @@ public final class AEnv
|
|||
}
|
||||
|
||||
/**
|
||||
* Workaround for detached HTML input element leak
|
||||
* @param c
|
||||
* Workaround for detached HTML input element leak.
|
||||
* <br/>
|
||||
* Detach all InputElement and Button that's the immediate or not immediate child of parent.
|
||||
* <br/>
|
||||
* Note that to remedy the detached HTML element leak issue, we must defer the detach of parent
|
||||
* with {@link Executions#schedule(Desktop, EventListener, Event)}.
|
||||
* @param parent {@link Component}
|
||||
*/
|
||||
public static void detachInputElement(Component c) {
|
||||
if (c instanceof InputElement || c instanceof Button) {
|
||||
c.detach();
|
||||
public static void detachInputElement(Component parent) {
|
||||
if (parent instanceof InputElement || parent instanceof Button) {
|
||||
parent.detach();
|
||||
}
|
||||
if (c.getChildren().size() > 0) {
|
||||
Component[] childs = c.getChildren().toArray(new Component[0]);
|
||||
for(Component c1 : childs) {
|
||||
detachInputElement(c1);
|
||||
if (parent.getChildren().size() > 0) {
|
||||
Component[] childs = parent.getChildren().toArray(new Component[0]);
|
||||
for(Component child : childs) {
|
||||
detachInputElement(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ import org.compiere.model.MUser;
|
|||
import org.compiere.model.MUserDefProc;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.model.SystemIDs;
|
||||
import org.compiere.model.X_AD_PInstance;
|
||||
import org.compiere.print.MPrintFormat;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.process.ProcessInfoUtil;
|
||||
|
@ -101,15 +102,22 @@ import org.zkoss.zul.Html;
|
|||
import org.zkoss.zul.Space;
|
||||
import org.zkoss.zul.Vlayout;
|
||||
|
||||
/**
|
||||
* Abstract dialog base class for execution of process/report.
|
||||
* @see ProcessModalDialog
|
||||
* @see ProcessDialog
|
||||
*/
|
||||
public abstract class AbstractProcessDialog extends Window implements IProcessUI, EventListener<Event>
|
||||
{
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = 484056046177205235L;
|
||||
|
||||
private static final String ON_COMPLETE = "onComplete";
|
||||
private static final String ON_STATUS_UPDATE = "onStatusUpdate";
|
||||
/** Event to fire on complete of execution of process/report **/
|
||||
private static final String ON_COMPLETE_EVENT = "onComplete";
|
||||
/** Event to update status text of process dialog. Event data: status text message. **/
|
||||
private static final String ON_STATUS_UPDATE_EVENT = "onStatusUpdate";
|
||||
|
||||
private static final CLogger log = CLogger.getCLogger(AbstractProcessDialog.class);
|
||||
|
||||
|
@ -118,29 +126,47 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
private Properties m_ctx;
|
||||
private int m_AD_Process_ID;
|
||||
private ProcessInfo m_pi = null;
|
||||
/** if true, auto call {@link #dispose()} in {@link #ON_COMPLETE_EVENT} handler. **/
|
||||
private boolean m_disposeOnComplete;
|
||||
|
||||
/** Panel for process paramters **/
|
||||
private ProcessParameterPanel parameterPanel = null;
|
||||
/** Checkbox to toggle running process/report as background job **/
|
||||
private Checkbox runAsJobField = null;
|
||||
private Label notificationTypeLabel = null;
|
||||
/**
|
||||
* Drop down editor for {@link X_AD_PInstance#NOTIFICATIONTYPE_AD_Reference_ID} list.
|
||||
* For background job notification when {@link #runAsJobField} is checked.
|
||||
*/
|
||||
private WTableDirEditor notificationTypeField = null;
|
||||
|
||||
private BusyDialog progressWindow;
|
||||
|
||||
/** translated process name */
|
||||
private String m_Name = null;
|
||||
/** translated process description */
|
||||
private String m_Description = null;
|
||||
/** translated process help */
|
||||
private String m_Help = null;
|
||||
private String m_ShowHelp = null; // Determine if a Help Process Window is shown
|
||||
/** Determine if a Help Process Window is shown **/
|
||||
private String m_ShowHelp = null;
|
||||
/** initial panel header message **/
|
||||
private String initialMessage;
|
||||
|
||||
/** true if dialog is still valid, i.e not dispose yet **/
|
||||
private boolean m_valid = true;
|
||||
/** true if dialog have been cancelled by user **/
|
||||
private boolean m_cancel = false;
|
||||
|
||||
/** Reference to process thread/task **/
|
||||
private Future<?> future;
|
||||
/** files for download by user **/
|
||||
private List<File> downloadFiles;
|
||||
/** true when UI have been locked, i.e busy **/
|
||||
private boolean m_locked = false;
|
||||
private String m_AD_Process_UU = "";
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
protected AbstractProcessDialog()
|
||||
{
|
||||
super();
|
||||
|
@ -163,7 +189,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
|
||||
/**
|
||||
* layout as below
|
||||
* layout dialog
|
||||
*
|
||||
* @param ctx
|
||||
* @param WindowNo
|
||||
|
@ -172,7 +198,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
* @param pi
|
||||
* @param autoStart
|
||||
* @param isDisposeOnComplete
|
||||
* @return
|
||||
* @return true if init is ok.
|
||||
*/
|
||||
protected boolean init(Properties ctx, int WindowNo, int TabNo, int AD_Process_ID, ProcessInfo pi, boolean autoStart, boolean isDisposeOnComplete)
|
||||
{
|
||||
|
@ -183,6 +209,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
setProcessInfo(pi);
|
||||
m_disposeOnComplete = isDisposeOnComplete;
|
||||
|
||||
if (log.isLoggable(Level.CONFIG))
|
||||
log.config("");
|
||||
//
|
||||
StringBuilder buildMsg = new StringBuilder();
|
||||
|
@ -222,7 +249,6 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
//
|
||||
this.setTitle(m_Name);
|
||||
|
||||
// Move from APanel.actionButton
|
||||
if (m_pi == null) {
|
||||
m_pi = new WProcessInfo(m_Name, AD_Process_ID);
|
||||
// Set Replace Tab Content
|
||||
|
@ -235,6 +261,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
|
||||
parameterPanel = new ProcessParameterPanel(m_WindowNo, m_TabNo, m_pi);
|
||||
if ( !parameterPanel.init() ) {
|
||||
//auto start if no parameters and DonTShowHelp.
|
||||
if (m_ShowHelp != null && MProcess.SHOWHELP_DonTShowHelp.equals(m_ShowHelp))
|
||||
autoStart = true;
|
||||
|
||||
|
@ -263,21 +290,33 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
return true;
|
||||
}
|
||||
|
||||
/** top part of {@link #mainParameterLayout} **/
|
||||
protected HtmlBasedComponent topParameterLayout;
|
||||
/** bottom part of {@link #mainParameterLayout} **/
|
||||
protected HtmlBasedComponent bottomParameterLayout;
|
||||
/** main content layout **/
|
||||
protected HtmlBasedComponent mainParameterLayout;
|
||||
protected WTableDirEditor fPrintFormat;
|
||||
private WEditor fLanguageType;
|
||||
protected Listbox freportType;
|
||||
private Checkbox chbIsSummary;
|
||||
/** ok button to run process/report **/
|
||||
protected Button bOK;
|
||||
/** cancel button to dismiss dialog **/
|
||||
protected Button bCancel;
|
||||
/** List of name/label for save process parameters **/
|
||||
protected Combobox fSavedName=new Combobox();
|
||||
/** button to save process parameters **/
|
||||
private Button bSave=ButtonFactory.createNamedButton("Save");
|
||||
/** button to delete saved process parameters **/
|
||||
private Button bDelete=ButtonFactory.createNamedButton("Delete");
|
||||
/** List of save parameters **/
|
||||
private List<MPInstance> savedParams;
|
||||
private Label lSaved;
|
||||
|
||||
/**
|
||||
* layout dialog
|
||||
*/
|
||||
protected void layout(){
|
||||
overalLayout();
|
||||
topLayout(topParameterLayout);
|
||||
|
@ -285,6 +324,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout {@link #mainParameterLayout}, {@link #topParameterLayout} and {@link #bottomParameterLayout}.
|
||||
*/
|
||||
protected void overalLayout(){
|
||||
mainParameterLayout = new Div();
|
||||
mainParameterLayout.setSclass("main-parameter-layout");
|
||||
|
@ -300,6 +342,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
mainParameterLayout.appendChild(bottomParameterLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout content of {@link #topParameterLayout}
|
||||
* @param topParameterLayout
|
||||
*/
|
||||
protected void topLayout(HtmlBasedComponent topParameterLayout) {
|
||||
// message
|
||||
setHeadMessage (topParameterLayout, initialMessage);
|
||||
|
@ -313,6 +359,12 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
inputParameterLayout(inputParameterLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create header message of {@link #topParameterLayout}
|
||||
* @param parent
|
||||
* @param contentMsg
|
||||
* @return content component for contentMsg
|
||||
*/
|
||||
protected HtmlBasedComponent setHeadMessage (HtmlBasedComponent parent, String contentMsg){
|
||||
// message
|
||||
HtmlBasedComponent messageParameterLayout = new Vlayout();
|
||||
|
@ -332,6 +384,11 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout parameter part of {@link #topParameterLayout}.
|
||||
* {@link #parameterPanel}, {@link #runAsJobField} and {@link #notificationTypeField}.
|
||||
* @param parent
|
||||
*/
|
||||
protected void inputParameterLayout (HtmlBasedComponent parent) {
|
||||
parent.appendChild(parameterPanel);
|
||||
|
||||
|
@ -403,6 +460,11 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout content of {@link #bottomParameterLayout}.
|
||||
* Report option, save parameter and action buttons.
|
||||
* @param bottomParameterLayout
|
||||
*/
|
||||
protected void bottomLayout(HtmlBasedComponent bottomParameterLayout) {
|
||||
reportOptionLayout(bottomParameterLayout);
|
||||
|
||||
|
@ -418,6 +480,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
buttonLayout (bottomContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render report option part of {@link #bottomParameterLayout}.
|
||||
* @param bottomParameterLayout
|
||||
*/
|
||||
protected void reportOptionLayout(HtmlBasedComponent bottomParameterLayout) {
|
||||
if (!isReport() && !isJasperReport())
|
||||
return;//if not a report not need show this pannel
|
||||
|
@ -428,6 +494,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
reportOptionLayout.setValign("middle");
|
||||
bottomParameterLayout.appendChild(reportOptionLayout);
|
||||
|
||||
//output type: html, pdf, etc
|
||||
Label lreportType = new Label(Msg.translate(Env.getCtx(), "view.report"));
|
||||
lreportType.setSclass("option-input-parameter view-report-label");
|
||||
freportType = new Listbox();
|
||||
|
@ -440,6 +507,8 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
|
||||
if (!isReport())
|
||||
return;
|
||||
|
||||
//summary option
|
||||
chbIsSummary = new Checkbox();
|
||||
chbIsSummary.setSclass("option-input-parameter");
|
||||
Label lPrintFormat = new Label(Msg.translate(Env.getCtx(), "AD_PrintFormat_ID"));
|
||||
|
@ -447,11 +516,13 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
Label lIsSummary = new Label(Msg.translate(Env.getCtx(), "Summary"));
|
||||
lIsSummary.setSclass("option-input-parameter");
|
||||
|
||||
//print formats
|
||||
MClient client = MClient.get(m_ctx);
|
||||
listPrintFormat(client);
|
||||
|
||||
reportOptionLayout.appendChild(lPrintFormat);
|
||||
reportOptionLayout.appendChild(fPrintFormat.getComponent());
|
||||
//selection of language
|
||||
if (client.isMultiLingualDocument()){
|
||||
Label lLanguageType = new Label(Msg.translate(Env.getCtx(), MLanguage.COLUMNNAME_AD_Language_ID));
|
||||
reportOptionLayout.appendChild(lLanguageType);
|
||||
|
@ -464,16 +535,26 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
reportOptionLayout.appendChild(chbIsSummary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if current process is with IsReport=Y AND JasperReport Is NULL.
|
||||
*/
|
||||
protected boolean isReport () {
|
||||
MProcess pr = MProcess.get(m_ctx, m_AD_Process_ID);
|
||||
return pr.isReport() && pr.getJasperReport() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if current process is with IsReport=Y AND JasperReport Is Not NULL.
|
||||
*/
|
||||
protected boolean isJasperReport () {
|
||||
MProcess pr = MProcess.get(m_ctx, m_AD_Process_ID);
|
||||
return pr.isReport() && pr.getJasperReport() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout UI to load/save process parameters
|
||||
* @param bottomParameterLayout
|
||||
*/
|
||||
protected void savePrameterLayout(HtmlBasedComponent bottomParameterLayout) {
|
||||
Hlayout savePrameterLayout = new Hlayout();
|
||||
savePrameterLayout.setSclass("save-parameter-container");
|
||||
|
@ -503,6 +584,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
querySaved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load saved process parameters
|
||||
*/
|
||||
protected void querySaved()
|
||||
{
|
||||
//user query
|
||||
|
@ -517,6 +601,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
fSavedName.setValue("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Action buttons for dialog
|
||||
* @param bottomParameterLayout
|
||||
*/
|
||||
protected void buttonLayout (HtmlBasedComponent bottomParameterLayout) {
|
||||
HtmlBasedComponent confParaPanel =new Div();
|
||||
confParaPanel.setSclass("button-container");
|
||||
|
@ -536,6 +624,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill {@link #fPrintFormat}
|
||||
* @param client
|
||||
*/
|
||||
private void listPrintFormat(MClient client)
|
||||
{
|
||||
int AD_Column_ID = 0;
|
||||
|
@ -590,6 +682,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
setReportTypeAndPrintFormat(getLastRun());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill {@link #freportType} for Jasper Report.
|
||||
*/
|
||||
private void listReportTypeJasper()
|
||||
{
|
||||
boolean m_isCanExport = MRole.getDefault().isCanExport();
|
||||
|
@ -598,6 +693,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
setReportTypeAndPrintFormat(getLastRun());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last run {@link MPInstance} record for current logged in user.
|
||||
*/
|
||||
protected MPInstance getLastRun() {
|
||||
final String where = "AD_Process_ID = ? AND AD_User_ID = ? AND Name IS NULL ";
|
||||
return new Query(Env.getCtx(), MPInstance.Table_Name, where, null)
|
||||
|
@ -607,6 +705,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
.first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill {@link #freportType}
|
||||
* @param m_isCanExport true to include excel and csv.
|
||||
*/
|
||||
private void fillReportType(boolean m_isCanExport) {
|
||||
freportType.removeAllItems();
|
||||
freportType.setMold("select");
|
||||
|
@ -623,6 +725,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
freportType.setSelectedIndex(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value for {@link #fPrintFormat}, {@link #fLanguageType}, {@link #freportType} and {@link #chbIsSummary} from instance.
|
||||
* @param instance
|
||||
*/
|
||||
private void setReportTypeAndPrintFormat(MPInstance instance)
|
||||
{
|
||||
if (fPrintFormat != null && instance != null
|
||||
|
@ -645,6 +751,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
chbIsSummary.setSelected(instance.isSummary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update process info ({@link ProcessInfo}) with selected report options ({@link #freportType},
|
||||
* {@link #fPrintFormat}, {@link #fLanguageType} and {@link #chbIsSummary}).
|
||||
*/
|
||||
protected void saveReportOption (){
|
||||
if (!isReport() && !isJasperReport()){
|
||||
return;
|
||||
|
@ -669,11 +779,16 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
getProcessInfo().setLanguageID(MLanguage.get(getCtx(), Env.getLanguage(getCtx())).getAD_Language_ID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto start process upon instantiation of process dialog.
|
||||
* Delegate to {@link #startProcess0()}.
|
||||
*/
|
||||
protected void autoStart()
|
||||
{
|
||||
startProcess0();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event)
|
||||
{
|
||||
Component component = event.getTarget();
|
||||
|
@ -683,9 +798,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
mainParameterLayout.invalidate();
|
||||
|
||||
}
|
||||
else if (event.getName().equals(ON_COMPLETE))
|
||||
else if (event.getName().equals(ON_COMPLETE_EVENT))
|
||||
onComplete();
|
||||
else if (event.getName().equals(ON_STATUS_UPDATE))
|
||||
else if (event.getName().equals(ON_STATUS_UPDATE_EVENT))
|
||||
onStatusUpdate(event);
|
||||
else if (event.getTarget().equals(bSave) || event.getTarget().equals(bDelete) || event.getTarget().equals(fSavedName)){
|
||||
String saveName = null;
|
||||
|
@ -708,6 +823,11 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save process parameters and report options.
|
||||
* Set MPInstance.Name = saveName.
|
||||
* @param saveName
|
||||
*/
|
||||
protected void updateSaveParameter(String saveName) {
|
||||
// Update existing
|
||||
if (fSavedName.getSelectedIndex() > -1 && savedParams != null) {
|
||||
|
@ -750,10 +870,15 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
log.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
|
||||
}
|
||||
}
|
||||
//reload fSavedName
|
||||
querySaved();
|
||||
fSavedName.setSelectedItem(getComboItem(saveName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save report options (output type, print format, language and IsSummary) to instance.
|
||||
* @param instance {@link MPInstance}
|
||||
*/
|
||||
protected void saveReportOptionToInstance (MPInstance instance){
|
||||
if (!isReport() && !isJasperReport())
|
||||
return;
|
||||
|
@ -782,6 +907,11 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
instance.setIsSummary(chbIsSummary.isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find {@link #fSavedName} item for value.
|
||||
* @param value
|
||||
* @return {@link Comboitem} found.
|
||||
*/
|
||||
public Comboitem getComboItem( String value) {
|
||||
Comboitem item = null;
|
||||
for (int i = 0; i < fSavedName.getItems().size(); i++) {
|
||||
|
@ -795,6 +925,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete saved MPInstance by saveName.
|
||||
* @param saveName
|
||||
*/
|
||||
protected void deleteSaveParameter(String saveName) {
|
||||
Object o = fSavedName.getSelectedItem();
|
||||
if (savedParams != null && o != null) {
|
||||
|
@ -808,6 +942,11 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
querySaved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load MPInstance by saveName.
|
||||
* @param saveName
|
||||
* @param lastRun
|
||||
*/
|
||||
protected void chooseSaveParameter(String saveName, boolean lastRun) {
|
||||
if (savedParams != null && saveName != null) {
|
||||
for (int i = 0; i < savedParams.size(); i++) {
|
||||
|
@ -820,14 +959,21 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
bSave.setEnabled(enabled && !lastRun);
|
||||
bDelete.setEnabled(enabled && fSavedName.getSelectedIndex() > -1
|
||||
&& !lastRun);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load parameter values and report options from instance.
|
||||
* @param instance {@link MPInstance}
|
||||
*/
|
||||
protected void loadSavedParams(MPInstance instance) {
|
||||
getParameterPanel().loadParameters(instance);
|
||||
setReportTypeAndPrintFormat(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run process.
|
||||
* Delegate to {@link #startProcess0()}.
|
||||
*/
|
||||
protected void startProcess()
|
||||
{
|
||||
if (!parameterPanel.validateParameters())
|
||||
|
@ -842,12 +988,19 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
startProcess0();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel/dismiss process dialog.
|
||||
*/
|
||||
protected void cancelProcess()
|
||||
{
|
||||
m_cancel = true;
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link #progressWindow}.
|
||||
* @return {@link BusyDialog}
|
||||
*/
|
||||
protected BusyDialog createBusyDialog()
|
||||
{
|
||||
progressWindow = new BusyDialog();
|
||||
|
@ -855,6 +1008,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
return progressWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close {@link #progressWindow}.
|
||||
*/
|
||||
protected void closeBusyDialog()
|
||||
{
|
||||
if (progressWindow != null) {
|
||||
|
@ -869,6 +1025,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
m_valid = false;
|
||||
} // dispose
|
||||
|
||||
/**
|
||||
* Run process.
|
||||
*/
|
||||
private void startProcess0()
|
||||
{
|
||||
if (!isBackgroundJob())
|
||||
|
@ -882,12 +1041,20 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
Clients.response(new AuEcho(this, isBackgroundJob() ? "runBackgroundJob" : "runProcess", this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run process. Echo event from {@link #startProcess0()}.
|
||||
*/
|
||||
public void runProcess()
|
||||
{
|
||||
Events.sendEvent(DialogEvents.ON_BEFORE_RUN_PROCESS, this, null);
|
||||
future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new ProcessDialogRunnable(null), getDesktop()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run process as background job (runBackgroundJob event echo from {@link #startProcess0()}).
|
||||
* <br/>
|
||||
* The different with {@link #runProcess()} is this method doesn't wait for completion of process.
|
||||
*/
|
||||
public void runBackgroundJob()
|
||||
{
|
||||
Properties m_ctx = getCtx();
|
||||
|
@ -959,6 +1126,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link #ON_COMPLETE_EVENT}
|
||||
*/
|
||||
private void onComplete()
|
||||
{
|
||||
ProcessInfo m_pi = getProcessInfo();
|
||||
|
@ -986,6 +1156,10 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link #ON_STATUS_UPDATE_EVENT}
|
||||
* @param event
|
||||
*/
|
||||
private void onStatusUpdate(Event event)
|
||||
{
|
||||
String message = (String) event.getData();
|
||||
|
@ -993,6 +1167,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
progressWindow.statusUpdate(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock UI by showing of busy dialog ({@link #progressWindow}).
|
||||
*/
|
||||
@Override
|
||||
public void lockUI(ProcessInfo pi) {
|
||||
if (m_locked || Executions.getCurrent() == null)
|
||||
|
@ -1001,8 +1178,14 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
showBusyDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show process in progress dialog.
|
||||
*/
|
||||
public abstract void showBusyDialog();
|
||||
|
||||
/**
|
||||
* Unlock dialog upon completion of process (or upon submission of job if process is running as background job).
|
||||
*/
|
||||
@Override
|
||||
public void unlockUI(ProcessInfo pi) {
|
||||
if (!m_locked)
|
||||
|
@ -1026,14 +1209,23 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close process in progress dialog and update UI with the result of process execution.
|
||||
*/
|
||||
private void doUnlockUI()
|
||||
{
|
||||
hideBusyDialog();
|
||||
updateUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close process in progress dialog.
|
||||
*/
|
||||
public abstract void hideBusyDialog();
|
||||
|
||||
/**
|
||||
* Update UI with the result of process execution.
|
||||
*/
|
||||
public abstract void updateUI();
|
||||
|
||||
@Override
|
||||
|
@ -1045,7 +1237,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
public void statusUpdate(String message) {
|
||||
Desktop desktop = getDesktop();
|
||||
if (desktop != null && desktop.isAlive())
|
||||
Executions.schedule(desktop, this, new Event(ON_STATUS_UPDATE, this, message));
|
||||
Executions.schedule(desktop, this, new Event(ON_STATUS_UPDATE_EVENT, this, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1064,20 +1256,21 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return ProcessInfo
|
||||
* @return {@link ProcessInfo}
|
||||
*/
|
||||
public ProcessInfo getProcessInfo() {
|
||||
return m_pi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pi
|
||||
*/
|
||||
public void setProcessInfo(ProcessInfo pi) {
|
||||
m_pi = pi;
|
||||
}
|
||||
|
||||
/**
|
||||
* is dialog still valid
|
||||
* @return boolean
|
||||
* @return true if dialog is still valid (i.e not completed and not cancel).
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
|
@ -1092,60 +1285,97 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
return m_cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return cache environment context reference
|
||||
*/
|
||||
public Properties getCtx()
|
||||
{
|
||||
return m_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return register window number.
|
||||
*/
|
||||
public int getWindowNo()
|
||||
{
|
||||
return m_WindowNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AD_Process_ID
|
||||
*/
|
||||
public int getAD_Process_ID()
|
||||
{
|
||||
return m_AD_Process_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link ProcessParameterPanel} instance
|
||||
*/
|
||||
public ProcessParameterPanel getParameterPanel()
|
||||
{
|
||||
return parameterPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return translated process name
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DonTShowHelp, ShowHelp or Silent.
|
||||
*/
|
||||
public String getShowHelp()
|
||||
{
|
||||
return m_ShowHelp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return initial panel header message
|
||||
*/
|
||||
public String getInitialMessage()
|
||||
{
|
||||
return initialMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if run process as background job.
|
||||
*/
|
||||
public boolean isBackgroundJob()
|
||||
{
|
||||
return runAsJobField != null && runAsJobField.isChecked();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Notification type - None, Email, Notice or Email+Notice.
|
||||
*/
|
||||
public String getNotificationType()
|
||||
{
|
||||
return (String) notificationTypeField.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of files for user download
|
||||
*/
|
||||
public List<File> getDownloadFiles()
|
||||
{
|
||||
return downloadFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable to run process in background thread.
|
||||
* Notify process dialog with {@link AbstractProcessDialog#ON_COMPLETE_EVENT} event.
|
||||
*/
|
||||
private class ProcessDialogRunnable extends ZkContextRunnable
|
||||
{
|
||||
private Trx m_trx;
|
||||
|
||||
/**
|
||||
* @param trx
|
||||
*/
|
||||
private ProcessDialogRunnable(Trx trx)
|
||||
{
|
||||
super();
|
||||
|
@ -1164,11 +1394,15 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
m_pi.setSummary(ex.getLocalizedMessage());
|
||||
log.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
|
||||
} finally {
|
||||
Executions.schedule(getDesktop(), AbstractProcessDialog.this, new Event(ON_COMPLETE, AbstractProcessDialog.this, null));
|
||||
Executions.schedule(getDesktop(), AbstractProcessDialog.this, new Event(ON_COMPLETE_EVENT, AbstractProcessDialog.this, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable to run process as background job.
|
||||
* Send email or notice notification to user upon completion of job.
|
||||
*/
|
||||
private class BackgroundJobRunnable implements Runnable
|
||||
{
|
||||
private Properties m_ctx;
|
||||
|
@ -1313,6 +1547,9 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
Dialog.askForInput(message, lookup, editorType, callback, getDesktop(), m_WindowNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge pdfList and show with {@link SimplePDFViewer}.
|
||||
*/
|
||||
@Override
|
||||
public void showReports(List<File> pdfList) {
|
||||
|
||||
|
|
|
@ -23,15 +23,24 @@ import org.zkoss.zul.Div;
|
|||
import org.zkoss.zul.Span;
|
||||
|
||||
/**
|
||||
*
|
||||
* Blocking in progress dialog.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class BusyDialog extends Window {
|
||||
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -779475945298887887L;
|
||||
/**
|
||||
* Label component to display in progress message (default is Processing...).
|
||||
*/
|
||||
private Label label;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public BusyDialog() {
|
||||
super();
|
||||
LayoutUtils.addSclass("busy-dialog", this);
|
||||
|
@ -55,6 +64,10 @@ public class BusyDialog extends Window {
|
|||
setShadow(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update in progress message.
|
||||
* @param message
|
||||
*/
|
||||
public void statusUpdate(String message) {
|
||||
if (label != null) {
|
||||
label.setText(message);
|
||||
|
|
|
@ -1,3 +1,28 @@
|
|||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* 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 General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
* - Richard Morales *
|
||||
**********************************************************************/
|
||||
package org.adempiere.webui.apps;
|
||||
|
||||
import org.adempiere.webui.component.Window;
|
||||
|
@ -5,18 +30,31 @@ import org.zkoss.zk.ui.event.Event;
|
|||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
|
||||
/**
|
||||
* Show {@link BusyDialog} and invoke {@link Runnable} task.
|
||||
* <br/>
|
||||
* Usage: new BusyDialogTemplate(runnable).run(); or with Lambda,new BusyDialogTemplate(() -> {your code}).run();
|
||||
*/
|
||||
public class BusyDialogTemplate implements Runnable, EventListener<Event> {
|
||||
|
||||
/** Event to call {@link #runnable} **/
|
||||
private static final String EVENT_NAME = "onRun";
|
||||
|
||||
/** Task to be invoked **/
|
||||
private Runnable runnable;
|
||||
|
||||
private BusyDialog busyDialog;
|
||||
|
||||
/**
|
||||
* @param runnable
|
||||
*/
|
||||
public BusyDialogTemplate(Runnable runnable) {
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide/dispose busy dialog
|
||||
*/
|
||||
private void hideBusyDialog() {
|
||||
if (busyDialog != null)
|
||||
{
|
||||
|
@ -25,12 +63,19 @@ public class BusyDialogTemplate implements Runnable, EventListener<Event> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show busy dialog in highlighted mode.
|
||||
*/
|
||||
private void showBusyDialog() {
|
||||
busyDialog = new BusyDialog();
|
||||
busyDialog.setAttribute(Window.MODE_KEY, Window.MODE_HIGHLIGHTED);
|
||||
AEnv.showCenterScreen(busyDialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #runnable} and close busy dialog.
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
try {
|
||||
if (event.getName().equals(EVENT_NAME)) {
|
||||
|
@ -41,6 +86,9 @@ public class BusyDialogTemplate implements Runnable, EventListener<Event> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show busy dialog and echo {@link #EVENT_NAME} to call {@link #runnable}
|
||||
*/
|
||||
public void run() {
|
||||
showBusyDialog();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import org.compiere.model.MLookup;
|
|||
import org.zkoss.zk.ui.Desktop;
|
||||
|
||||
/**
|
||||
* Callout Dialog used for Ask For Input
|
||||
* Callout Dialog used to ask for input from user.
|
||||
*
|
||||
* @author Murilo H. Torquato (devCoffee, http://devcoffee.com.br)
|
||||
*
|
||||
|
@ -31,6 +31,10 @@ public class CalloutDialog implements ICalloutUI {
|
|||
private Desktop desktop;
|
||||
private int m_windowNo;
|
||||
|
||||
/**
|
||||
* @param desktop
|
||||
* @param windowNo
|
||||
*/
|
||||
public CalloutDialog(Desktop desktop, int windowNo) {
|
||||
this.desktop = desktop;
|
||||
this.m_windowNo = windowNo;
|
||||
|
|
|
@ -1,6 +1,27 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* 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 General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
**********************************************************************/
|
||||
package org.adempiere.webui.apps;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -14,10 +35,12 @@ import org.zkoss.zk.ui.Desktop;
|
|||
*
|
||||
*/
|
||||
public class DesktopRunnable implements Runnable {
|
||||
|
||||
/** wrapped runnable **/
|
||||
private Runnable runnable;
|
||||
/** weak reference to Desktop **/
|
||||
private WeakReference<Desktop> desktopWeakRef;
|
||||
|
||||
/** ThreadLocal weak reference to Desktop **/
|
||||
private static ThreadLocal<WeakReference<Desktop>> threadLocalDesktop = new ThreadLocal<WeakReference<Desktop>>() {
|
||||
protected WeakReference<Desktop> initialValue()
|
||||
{
|
||||
|
@ -25,13 +48,17 @@ public class DesktopRunnable implements Runnable {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param runnable
|
||||
* @param desktop
|
||||
*/
|
||||
public DesktopRunnable(Runnable runnable, Desktop desktop) {
|
||||
this.runnable = runnable;
|
||||
this.desktopWeakRef = new WeakReference<Desktop>(desktop);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
/**
|
||||
* Set thread local Desktop reference and call {@link #runnable}.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
|
@ -53,20 +53,29 @@ import org.zkoss.zul.Vlayout;
|
|||
*/
|
||||
public class DocumentSearchController implements EventListener<Event>{
|
||||
|
||||
/** {@link A} component attribute to hold reference to corresponding {@link #SEARCH_RESULT} **/
|
||||
private static final String SEARCH_RESULT = "search.result";
|
||||
private static final String ON_SEARCH_DOCUMENTS = "onSearchDocuments";
|
||||
/** onSearchDocuments event **/
|
||||
private static final String ON_SEARCH_DOCUMENTS_EVENT = "onSearchDocuments";
|
||||
private int MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER = 3;
|
||||
/** layout to show links ({@link A}) for each {@link #SEARCH_RESULT} in {@link #list} **/
|
||||
private Vlayout layout;
|
||||
/** results from execution of search **/
|
||||
private ArrayList<SearchResult> list;
|
||||
/** Current selected index of {@link #list} **/
|
||||
private int selected = -1;
|
||||
|
||||
/**
|
||||
*
|
||||
* default constructor
|
||||
*/
|
||||
public DocumentSearchController() {
|
||||
MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER = MSysConfig.getIntValue(MSysConfig.MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER, 3, Env.getAD_Client_ID(Env.getCtx()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create {@link #layout} for search result
|
||||
* @param parent
|
||||
*/
|
||||
public void create(Component parent) {
|
||||
layout = new Vlayout();
|
||||
layout.setStyle("padding: 3px; overflow:auto;");
|
||||
|
@ -75,14 +84,23 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
|
||||
parent.appendChild(layout);
|
||||
|
||||
layout.addEventListener(ON_SEARCH_DOCUMENTS, this);
|
||||
layout.addEventListener(ON_SEARCH_DOCUMENTS_EVENT, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo {@link #ON_SEARCH_DOCUMENTS_EVENT} with value as event data.
|
||||
* @param value
|
||||
*/
|
||||
public void search(String value) {
|
||||
layout.getChildren().clear();
|
||||
Events.echoEvent(ON_SEARCH_DOCUMENTS, layout, value);
|
||||
Events.echoEvent(ON_SEARCH_DOCUMENTS_EVENT, layout, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link #ON_SEARCH_DOCUMENTS_EVENT} event.
|
||||
* Delegate execution of search to {@link #doSearch(String)}.
|
||||
* @param searchString
|
||||
*/
|
||||
private void onSearchDocuments(String searchString) {
|
||||
list = new ArrayList<SearchResult>();
|
||||
if (Util.isEmpty(searchString)) {
|
||||
|
@ -119,6 +137,11 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform search with searchString using definition from AD_SearchDefinition.
|
||||
* @param searchString
|
||||
* @return List of {@link SearchResult}
|
||||
*/
|
||||
private List<SearchResult> doSearch(String searchString) {
|
||||
final MRole role = MRole.get(Env.getCtx(), Env.getAD_Role_ID(Env.getCtx()), Env.getAD_User_ID(Env.getCtx()), true);
|
||||
|
||||
|
@ -199,6 +222,17 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute query and output result to list.
|
||||
* @param msd
|
||||
* @param builder
|
||||
* @param params
|
||||
* @param lookup
|
||||
* @param window
|
||||
* @param tableName
|
||||
* @param extraWhereClase
|
||||
* @param list
|
||||
*/
|
||||
private void doRetrieval(MSearchDefinition msd, StringBuilder builder, List<Object> params, MLookup lookup, MWindow window, String tableName,
|
||||
String extraWhereClase, List<SearchResult> list) {
|
||||
PreparedStatement pstmt = null;
|
||||
|
@ -250,17 +284,24 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
SearchResult result = (SearchResult) event.getTarget().getAttribute(SEARCH_RESULT);
|
||||
doZoom(result);
|
||||
}
|
||||
} else if (event.getName().equals(ON_SEARCH_DOCUMENTS)) {
|
||||
} else if (event.getName().equals(ON_SEARCH_DOCUMENTS_EVENT)) {
|
||||
onSearchDocuments((String)event.getData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom to AD Window
|
||||
* @param result
|
||||
*/
|
||||
private void doZoom(SearchResult result) {
|
||||
MQuery query = new MQuery();
|
||||
query.addRestriction(result.getTableName()+"_ID", "=", result.getRecordId());
|
||||
AEnv.zoom(result.getWindowId(), query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value class to hold search result
|
||||
*/
|
||||
public static class SearchResult {
|
||||
private String windowName;
|
||||
private int windowId;
|
||||
|
@ -344,6 +385,13 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find {@link SearchResult} link from {@link #layout} that matches text from textbox.
|
||||
* <br/>
|
||||
* Call {@link #doZoom(SearchResult)} if a match is found.
|
||||
* @param textbox
|
||||
* @return true if a match is found
|
||||
*/
|
||||
public boolean onOk(Textbox textbox) {
|
||||
String text = textbox.getText();
|
||||
if (Util.isEmpty(text))
|
||||
|
@ -374,11 +422,16 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
result = (SearchResult) firstStart.getAttribute(SEARCH_RESULT);
|
||||
if (result != null) {
|
||||
doZoom(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select and return {@link SearchResult} that comes before the current selected {@link SearchResult} link in {@link #layout}.
|
||||
* @return {@link SearchResult}
|
||||
*/
|
||||
public SearchResult selectPrior() {
|
||||
if (selected > 0) {
|
||||
selected--;
|
||||
|
@ -399,6 +452,10 @@ public class DocumentSearchController implements EventListener<Event>{
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select and return {@link SearchResult} that comes after the current selected {@link SearchResult} link in {@link #layout}.
|
||||
* @return {@link SearchResult}
|
||||
*/
|
||||
public SearchResult selectNext() {
|
||||
if (selected < (list.size()-1)) {
|
||||
selected++;
|
||||
|
|
|
@ -64,7 +64,7 @@ import org.zkoss.zul.Div;
|
|||
import org.zkoss.zul.South;
|
||||
|
||||
/**
|
||||
*
|
||||
* Window to capture feedback request from user.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
|
@ -77,13 +77,19 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
|
||||
private static final CLogger log = CLogger.getCLogger(FeedbackRequestWindow.class);
|
||||
|
||||
/** Fields for {@link MRequest} **/
|
||||
protected WTableDirEditor requestTypeField, priorityField, salesRepField;
|
||||
protected Textbox txtSummary;
|
||||
protected ConfirmPanel confirmPanel;
|
||||
|
||||
/** attachments uploaded by user **/
|
||||
protected List<DataSource> attachments = new ArrayList<DataSource>();
|
||||
/** Div to host list of {@link AttachmentItem} **/
|
||||
protected Div attachmentBox;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public FeedbackRequestWindow() {
|
||||
|
||||
super();
|
||||
|
@ -114,6 +120,7 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
throw new RuntimeException(Msg.getMsg(Env.getCtx(), "AccessTableNoUpdate"));
|
||||
}
|
||||
|
||||
//layout window
|
||||
Label lblRequestType = new Label(Msg.getElement(Env.getCtx(), "R_RequestType_ID"));
|
||||
Label lblPriority = new Label(Msg.getElement(Env.getCtx(), "Priority"));
|
||||
Label lblSummary = new Label(Msg.getElement(Env.getCtx(), "Summary"));
|
||||
|
@ -236,6 +243,7 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
addAttachment(FeedbackManager.getLogAttachment(false), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event e) throws Exception {
|
||||
if (e.getTarget() == confirmPanel.getButton(ConfirmPanel.A_OK)) {
|
||||
Clients.clearBusy();
|
||||
|
@ -271,6 +279,10 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save request
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void saveRequest() throws IOException {
|
||||
Trx trx = Trx.get(Trx.createTrxName("SaveNewRequest"), true);
|
||||
trx.setDisplayName(getClass().getName()+"_saveRequest");
|
||||
|
@ -315,6 +327,11 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new MRequest record.
|
||||
* @param trx
|
||||
* @return {@link MRequest}
|
||||
*/
|
||||
protected MRequest createMRequest(Trx trx) {
|
||||
MRequest request = new MRequest(Env.getCtx(), 0, trx.getTrxName());
|
||||
request.setAD_Org_ID(Env.getAD_Org_ID(Env.getCtx()));
|
||||
|
@ -325,6 +342,11 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachment from user.
|
||||
* @param dataSource
|
||||
* @param removable
|
||||
*/
|
||||
public void addAttachment(DataSource dataSource, boolean removable) {
|
||||
attachments.add(dataSource);
|
||||
AttachmentItem item = new AttachmentItem(dataSource, attachments, removable);
|
||||
|
@ -332,6 +354,11 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
getFirstChild().invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get byte[] from media.
|
||||
* @param media
|
||||
* @return byte[]
|
||||
*/
|
||||
private byte[] getMediaData(Media media) {
|
||||
byte[] bytes = null;
|
||||
|
||||
|
@ -358,6 +385,11 @@ public class FeedbackRequestWindow extends Window implements EventListener<Event
|
|||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get character set from contentType (i.e from charset=).
|
||||
* @param contentType
|
||||
* @return character set (default is UTF-8)
|
||||
*/
|
||||
private String getCharset(String contentType) {
|
||||
if (contentType != null) {
|
||||
int j = contentType.indexOf("charset=");
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.adempiere.webui.component.Tabpanels;
|
|||
import org.adempiere.webui.component.Tabs;
|
||||
import org.adempiere.webui.util.DocumentSearch;
|
||||
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||
import org.compiere.model.MSearchDefinition;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
@ -37,19 +38,27 @@ import org.zkoss.zul.Bandpopup;
|
|||
import org.zkoss.zul.Div;
|
||||
|
||||
/**
|
||||
* Global search component at desktop header.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class GlobalSearch extends Div implements EventListener<Event> {
|
||||
|
||||
private static final String ON_ENTER_KEY = "onEnterKey";
|
||||
/** {@link #bandbox} attribute to store value from last {@link Events#ON_CHANGING} event **/
|
||||
private static final String LAST_ONCHANGING_ATTR = "last.onchanging";
|
||||
|
||||
private static final String ON_POST_ENTER_KEY = "onPostEnterKey";
|
||||
/** Event send from client side upon keyDown of enter key **/
|
||||
private static final String ON_ENTER_KEY_EVENT = "onEnterKey";
|
||||
|
||||
private static final String ON_CREATE_ECHO = "onCreateEcho";
|
||||
/** Event echo from ON_ENTER_KEY_EVENT to allow showing of in progress dialog before execution of search **/
|
||||
private static final String ON_POST_ENTER_KEY_EVENT = "onPostEnterKey";
|
||||
|
||||
private static final String ON_SEARCH = "onSearch";
|
||||
/** Event echo from {@link #onPageAttached(Page, Page)} **/
|
||||
private static final String ON_CREATE_ECHO_EVENT = "onCreateEcho";
|
||||
|
||||
/** Event to execute search. **/
|
||||
private static final String ON_SEARCH_EVENT = "onSearch";
|
||||
|
||||
/** Prefix to start document search using definition from {@link MSearchDefinition} **/
|
||||
private static final String PREFIX_DOCUMENT_SEARCH = "/";
|
||||
|
||||
/**
|
||||
|
@ -57,15 +66,20 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
*/
|
||||
private static final long serialVersionUID = -8793878697269469837L;
|
||||
|
||||
/** Bandbox to capture search text from user and display result in popup **/
|
||||
private Bandbox bandbox;
|
||||
|
||||
/** controller to search AD_Menu **/
|
||||
private MenuSearchController menuController;
|
||||
|
||||
/** controller to search tables **/
|
||||
private DocumentSearchController docController;
|
||||
|
||||
/** tabbox to host menu and document search tab **/
|
||||
private Tabbox tabbox;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param menuController
|
||||
*/
|
||||
public GlobalSearch(MenuSearchController menuController) {
|
||||
this.menuController = menuController;
|
||||
|
@ -73,11 +87,13 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout UI and setup listeners
|
||||
*/
|
||||
private void init() {
|
||||
bandbox = new Bandbox();
|
||||
bandbox.setSclass("global-search-box");
|
||||
appendChild(bandbox);
|
||||
// ZKUpdateUtil.setWidth(bandbox, "100%");
|
||||
bandbox.setAutodrop(true);
|
||||
bandbox.setId("globalSearchBox");
|
||||
bandbox.addEventListener(Events.ON_CHANGING, this);
|
||||
|
@ -114,22 +130,24 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
tabPanels.appendChild(tabPanel);
|
||||
docController.create(tabPanel);
|
||||
|
||||
addEventListener(ON_SEARCH, this);
|
||||
addEventListener(ON_CREATE_ECHO, this);
|
||||
bandbox.addEventListener(ON_ENTER_KEY, this);
|
||||
addEventListener(ON_POST_ENTER_KEY, this);
|
||||
addEventListener(ON_SEARCH_EVENT, this);
|
||||
addEventListener(ON_CREATE_ECHO_EVENT, this);
|
||||
bandbox.addEventListener(ON_ENTER_KEY_EVENT, this);
|
||||
addEventListener(ON_POST_ENTER_KEY_EVENT, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
if (Events.ON_CHANGING.equals(event.getName())) {
|
||||
//post ON_SEARCH_EVENT for ON_CHANGING from bandbox
|
||||
InputEvent inputEvent = (InputEvent) event;
|
||||
String value = inputEvent.getValue();
|
||||
bandbox.setAttribute("last.onchanging", value);
|
||||
Events.postEvent(ON_SEARCH, this, value);
|
||||
bandbox.setAttribute(LAST_ONCHANGING_ATTR, value);
|
||||
Events.postEvent(ON_SEARCH_EVENT, this, value);
|
||||
} else if (Events.ON_CHANGE.equals(event.getName())) {
|
||||
bandbox.removeAttribute("last.onchanging");
|
||||
bandbox.removeAttribute(LAST_ONCHANGING_ATTR);
|
||||
} else if (Events.ON_CTRL_KEY.equals(event.getName())) {
|
||||
//handle keyboard navigation for bandbox items
|
||||
KeyEvent ke = (KeyEvent) event;
|
||||
if (ke.getKeyCode() == KeyEvent.UP) {
|
||||
if (bandbox.getFirstChild().isVisible()) {
|
||||
|
@ -160,28 +178,30 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (event.getName().equals(ON_SEARCH)) {
|
||||
} else if (event.getName().equals(ON_SEARCH_EVENT)) {
|
||||
String value = (String) event.getData();
|
||||
if (tabbox.getSelectedIndex()==0)
|
||||
menuController.search(value);
|
||||
else
|
||||
docController.search(value);
|
||||
bandbox.focus();
|
||||
} else if (event.getName().equals(ON_CREATE_ECHO)) {
|
||||
} else if (event.getName().equals(ON_CREATE_ECHO_EVENT)) {
|
||||
//setup client side listener for enter key
|
||||
StringBuilder script = new StringBuilder("jq('#")
|
||||
.append(bandbox.getUuid())
|
||||
.append("').bind('keydown', function(e) {let code=e.keyCode||e.which;if(code==13){")
|
||||
.append("let widget=zk.Widget.$(this);")
|
||||
.append("let event=new zk.Event(widget,'")
|
||||
.append(ON_ENTER_KEY)
|
||||
.append(ON_ENTER_KEY_EVENT)
|
||||
.append("',{},{toServer:true});")
|
||||
.append("zAu.send(event);")
|
||||
.append("}});");
|
||||
Clients.evalJavaScript(script.toString());
|
||||
} else if (event.getName().equals(ON_ENTER_KEY)) {
|
||||
} else if (event.getName().equals(ON_ENTER_KEY_EVENT)) {
|
||||
Clients.showBusy(bandbox, null);
|
||||
Events.echoEvent(ON_POST_ENTER_KEY, this, null);
|
||||
} else if (event.getName().equals(ON_POST_ENTER_KEY)) {
|
||||
Events.echoEvent(ON_POST_ENTER_KEY_EVENT, this, null);
|
||||
} else if (event.getName().equals(ON_POST_ENTER_KEY_EVENT)) {
|
||||
//execute search trigger by press of enter key
|
||||
Clients.clearBusy(bandbox);
|
||||
if (bandbox.getValue() != null && bandbox.getValue().startsWith(PREFIX_DOCUMENT_SEARCH)) {
|
||||
DocumentSearch search = new DocumentSearch();
|
||||
|
@ -195,11 +215,11 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
}
|
||||
}
|
||||
} else if (event.getName().equals(Events.ON_SELECT)) {
|
||||
String value = (String) bandbox.getAttribute("last.onchanging");
|
||||
String value = (String) bandbox.getAttribute(LAST_ONCHANGING_ATTR);
|
||||
if (value == null) {
|
||||
value = bandbox.getValue();
|
||||
}
|
||||
Events.postEvent(ON_SEARCH, this, value);
|
||||
Events.postEvent(ON_SEARCH_EVENT, this, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,15 +229,21 @@ public class GlobalSearch extends Div implements EventListener<Event> {
|
|||
@Override
|
||||
public void onPageAttached(Page newpage, Page oldpage) {
|
||||
super.onPageAttached(newpage, oldpage);
|
||||
Events.echoEvent(ON_CREATE_ECHO, this, null);
|
||||
Events.echoEvent(ON_CREATE_ECHO_EVENT, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close {@link #bandbox} popup.
|
||||
*/
|
||||
public void closePopup() {
|
||||
if (bandbox != null) {
|
||||
bandbox.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client info event from browser.
|
||||
*/
|
||||
public void onClientInfo() {
|
||||
ZKUpdateUtil.setWindowHeightX(bandbox.getDropdown(), ClientInfo.get().desktopHeight-50);
|
||||
}
|
||||
|
|
|
@ -38,15 +38,21 @@ import org.zkoss.zul.Center;
|
|||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.Html;
|
||||
|
||||
/**
|
||||
* Help for AD Window with contents generated from AD definition.
|
||||
*/
|
||||
public class HelpWindow extends Window {
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -7353411576541612026L;
|
||||
|
||||
private GridWindow gridWindow;
|
||||
private String winpref;
|
||||
|
||||
/**
|
||||
* @param gridWindow
|
||||
*/
|
||||
public HelpWindow(GridWindow gridWindow)
|
||||
{
|
||||
super();
|
||||
|
@ -95,6 +101,9 @@ public class HelpWindow extends Window {
|
|||
html.setContent(doc.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return header {@link table}
|
||||
*/
|
||||
private table getHeader()
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -180,6 +189,9 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return content {@link table}
|
||||
*/
|
||||
private table getContent()
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -202,6 +214,9 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return content {@link table} for left pane
|
||||
*/
|
||||
private table getLeftContent()
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -223,6 +238,9 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return content {@link table} for right pane
|
||||
*/
|
||||
private table getRightContent()
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -273,6 +291,12 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name, description and help text for AD_Tab
|
||||
* @param tab
|
||||
* @param tabIndex
|
||||
* @return {@link table} with name, description and help text
|
||||
*/
|
||||
private table getTabBox(GridTab tab, int tabIndex)
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -326,6 +350,12 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Links for all display field
|
||||
* @param tab
|
||||
* @param tabIndex
|
||||
* @return {@link table} with link for all display fields
|
||||
*/
|
||||
private table getFieldsBox(GridTab tab, int tabIndex)
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
@ -383,6 +413,13 @@ public class HelpWindow extends Window {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* header/label, description and help text for a field.
|
||||
* @param field
|
||||
* @param tabIndex
|
||||
* @param fieldIndex
|
||||
* @return {@link table} with header/label, description and help text
|
||||
*/
|
||||
private table getFieldBox(GridField field, int tabIndex, int fieldIndex)
|
||||
{
|
||||
table table = new table("0", "0", "0", "100%", null);
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.adempiere.webui.editor.WEditor;
|
|||
|
||||
/**
|
||||
* Listener interface for process parameter panel.
|
||||
* Implementation must be thread safe
|
||||
* Implementation must be thread safe.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -42,16 +42,29 @@ import org.zkoss.zk.ui.util.Clients;
|
|||
import org.zkoss.zul.Bandpopup;
|
||||
import org.zkoss.zul.Div;
|
||||
|
||||
/**
|
||||
* Component to search AD_Label* records.
|
||||
*/
|
||||
public class LabelsSearch extends Div implements EventListener<Event> {
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -8793878697269469837L;
|
||||
private static final String ON_ENTER_KEY = "onEnterKey";
|
||||
private static final String ON_CREATE_ECHO = "onCreateEcho";
|
||||
private static final String ON_SEARCH = "onSearch";
|
||||
/** Event send from client side upon keyDown of enter key **/
|
||||
private static final String ON_ENTER_KEY_EVENT = "onEnterKey";
|
||||
/** Event echo from {@link #onPageAttached(Page, Page)} **/
|
||||
private static final String ON_CREATE_ECHO_EVENT = "onCreateEcho";
|
||||
/** Event to execute search. **/
|
||||
private static final String ON_SEARCH_EVENT = "onSearch";
|
||||
/** {@link #bandbox} attribute to store value from last {@link Events#ON_CHANGING} event **/
|
||||
private static final String LAST_ONCHANGING_ATTR = "last.onchanging";
|
||||
/** Bandbox to capture search text from user and display result in popup **/
|
||||
private Bandbox bandbox;
|
||||
/** Controller to perform search on AD_Label* records **/
|
||||
private LabelsSearchController controller;
|
||||
|
||||
/**
|
||||
* Standard constructot
|
||||
* Standard constructor
|
||||
* @param controller
|
||||
*/
|
||||
public LabelsSearch(LabelsSearchController controller) {
|
||||
|
@ -59,6 +72,9 @@ public class LabelsSearch extends Div implements EventListener<Event> {
|
|||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout UI and setup listeners
|
||||
*/
|
||||
private void init() {
|
||||
bandbox = new Bandbox();
|
||||
appendChild(bandbox);
|
||||
|
@ -77,22 +93,24 @@ public class LabelsSearch extends Div implements EventListener<Event> {
|
|||
bandbox.appendChild(popup);
|
||||
controller.create(popup);
|
||||
|
||||
addEventListener(ON_SEARCH, this);
|
||||
addEventListener(ON_CREATE_ECHO, this);
|
||||
addEventListener(ON_SEARCH_EVENT, this);
|
||||
addEventListener(ON_CREATE_ECHO_EVENT, this);
|
||||
addEventListener(LabelsSearchController.ON_POST_SELECT_LABELITEM_EVENT, this);
|
||||
bandbox.addEventListener(ON_ENTER_KEY, this);
|
||||
bandbox.addEventListener(ON_ENTER_KEY_EVENT, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
if (Events.ON_CHANGING.equals(event.getName())) {
|
||||
//post ON_SEARCH_EVENT for ON_CHANGING event from bandbox
|
||||
InputEvent inputEvent = (InputEvent) event;
|
||||
String value = inputEvent.getValue();
|
||||
bandbox.setAttribute("last.onchanging", value);
|
||||
Events.postEvent(ON_SEARCH, this, value);
|
||||
bandbox.setAttribute(LAST_ONCHANGING_ATTR, value);
|
||||
Events.postEvent(ON_SEARCH_EVENT, this, value);
|
||||
} else if (Events.ON_CHANGE.equals(event.getName())) {
|
||||
bandbox.removeAttribute("last.onchanging");
|
||||
bandbox.removeAttribute(LAST_ONCHANGING_ATTR);
|
||||
} else if (Events.ON_CTRL_KEY.equals(event.getName())) {
|
||||
//handle keyboard navigation for bandbox items
|
||||
KeyEvent ke = (KeyEvent) event;
|
||||
if (ke.getKeyCode() == KeyEvent.UP) {
|
||||
if (bandbox.getFirstChild().isVisible()) {
|
||||
|
@ -111,32 +129,33 @@ public class LabelsSearch extends Div implements EventListener<Event> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (event.getName().equals(ON_SEARCH)) {
|
||||
} else if (event.getName().equals(ON_SEARCH_EVENT)) {
|
||||
String value = (String) event.getData();
|
||||
controller.search(value);
|
||||
bandbox.focus();
|
||||
} else if (event.getName().equals(ON_CREATE_ECHO)) {
|
||||
} else if (event.getName().equals(ON_CREATE_ECHO_EVENT)) {
|
||||
//setup client side keyDown listener for enter key
|
||||
StringBuilder script = new StringBuilder("jq('#")
|
||||
.append(bandbox.getUuid())
|
||||
.append("').bind('keydown', function(e) {var code=e.keyCode||e.which;if(code==13){")
|
||||
.append("var widget=zk.Widget.$(this);")
|
||||
.append("var event=new zk.Event(widget,'")
|
||||
.append(ON_ENTER_KEY)
|
||||
.append(ON_ENTER_KEY_EVENT)
|
||||
.append("',{},{toServer:true});")
|
||||
.append("zAu.send(event);")
|
||||
.append("}});");
|
||||
Clients.evalJavaScript(script.toString());
|
||||
} else if (event.getName().equals(ON_ENTER_KEY)) {
|
||||
} else if (event.getName().equals(ON_ENTER_KEY_EVENT)) {
|
||||
if (event.getTarget() instanceof Bandbox) {
|
||||
controller.onSelect(controller.getSelectedItem());
|
||||
}
|
||||
} else if (event.getName().equals(Events.ON_SELECT)) {
|
||||
String value = (String) bandbox.getAttribute("last.onchanging");
|
||||
String value = (String) bandbox.getAttribute(LAST_ONCHANGING_ATTR);
|
||||
if (value == null) {
|
||||
value = bandbox.getValue();
|
||||
}
|
||||
|
||||
Events.postEvent(ON_SEARCH, this, value);
|
||||
Events.postEvent(ON_SEARCH_EVENT, this, value);
|
||||
}
|
||||
|
||||
if (event.getName().equals(LabelsSearchController.ON_POST_SELECT_LABELITEM_EVENT)) {
|
||||
|
@ -150,11 +169,11 @@ public class LabelsSearch extends Div implements EventListener<Event> {
|
|||
@Override
|
||||
public void onPageAttached(Page newpage, Page oldpage) {
|
||||
super.onPageAttached(newpage, oldpage);
|
||||
Events.echoEvent(ON_CREATE_ECHO, this, null);
|
||||
Events.echoEvent(ON_CREATE_ECHO_EVENT, this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the search dropdown
|
||||
* Close {@link #bandbox} popup
|
||||
*/
|
||||
public void closePopup() {
|
||||
if (bandbox != null) {
|
||||
|
@ -163,7 +182,7 @@ public class LabelsSearch extends Div implements EventListener<Event> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set height of the search dropdown
|
||||
* Set height {@link #bandbox} dropdown
|
||||
*/
|
||||
public void onClientInfo() {
|
||||
ZKUpdateUtil.setWindowHeightX(bandbox.getDropdown(), ClientInfo.get().desktopHeight-50);
|
||||
|
|
|
@ -56,14 +56,25 @@ import org.zkoss.zul.ListitemRenderer;
|
|||
import org.zkoss.zul.ListitemRendererExt;
|
||||
import org.zkoss.zul.Vlayout;
|
||||
|
||||
/**
|
||||
* Controller for search on AD_Label* records.
|
||||
*/
|
||||
public class LabelsSearchController implements EventListener<Event>{
|
||||
/** Event echo from {@link #onSelect(LabelItem)} **/
|
||||
public static final String ON_POST_SELECT_LABELITEM_EVENT = "onPostSelectLabelitem";
|
||||
private static final String ON_SEARCH_ECHO = "onSearchEcho";
|
||||
private static final String ON_LOAD_MORE = "onLoadMore";
|
||||
/** Event echo to initiate search for a given input text **/
|
||||
private static final String ON_SEARCH_ECHO_EVENT = "onSearchEcho";
|
||||
/** TODO: not used, candidate for removal **/
|
||||
private static final String ON_LOAD_MORE_EVENT = "onLoadMore";
|
||||
/** parent of {@link #layout} **/
|
||||
private Component parent;
|
||||
/** Listbox to display search result **/
|
||||
private Listbox listbox;
|
||||
/** model for {@link #listbox} **/
|
||||
private ListModelList<LabelItem> model;
|
||||
/** main layout **/
|
||||
private Vlayout layout;
|
||||
/** label window panel, provider for AD_Table_ID and Record_ID **/
|
||||
private LabelsPanel labelsPanel;
|
||||
|
||||
/**
|
||||
|
@ -103,13 +114,13 @@ public class LabelsSearchController implements EventListener<Event>{
|
|||
ZKUpdateUtil.setWidth(listheader, "30px");
|
||||
listhead.appendChild(listheader);
|
||||
|
||||
layout.addEventListener(ON_SEARCH_ECHO, this);
|
||||
layout.addEventListener(ON_LOAD_MORE, this);
|
||||
layout.addEventListener(ON_SEARCH_ECHO_EVENT, this);
|
||||
layout.addEventListener(ON_LOAD_MORE_EVENT, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
if (event.getName().equals(ON_SEARCH_ECHO)) {
|
||||
if (event.getName().equals(ON_SEARCH_ECHO_EVENT)) {
|
||||
onSearchEcho((String) event.getData());
|
||||
} else if (Events.ON_CLICK.equals(event.getName())) {
|
||||
if (event.getTarget() instanceof ListItem) {
|
||||
|
@ -121,16 +132,16 @@ public class LabelsSearchController implements EventListener<Event>{
|
|||
}
|
||||
|
||||
/**
|
||||
* Search for a given text
|
||||
* Echo {@link #ON_SEARCH_ECHO_EVENT} to initiate search for value
|
||||
* @param value
|
||||
*/
|
||||
public void search(String value) {
|
||||
listbox.setModel((ListModel<?>)null);
|
||||
Events.echoEvent(ON_SEARCH_ECHO, layout, value);
|
||||
Events.echoEvent(ON_SEARCH_ECHO_EVENT, layout, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a given text
|
||||
* Handle {@link #ON_SEARCH_ECHO_EVENT} to execute search for a given text
|
||||
* @param value
|
||||
*/
|
||||
public void onSearchEcho(String value) {
|
||||
|
|
|
@ -1,22 +1,50 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
/***********************************************************************
|
||||
* This file is part of iDempiere ERP Open Source *
|
||||
* http://www.idempiere.org *
|
||||
* *
|
||||
* Copyright (C) Contributors *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* 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 General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||
* MA 02110-1301, USA. *
|
||||
* *
|
||||
* Contributors: *
|
||||
* - hengsin *
|
||||
**********************************************************************/
|
||||
package org.adempiere.webui.apps;
|
||||
|
||||
import org.zkoss.zul.DefaultTreeNode;
|
||||
import org.zkoss.zul.Treeitem;
|
||||
|
||||
/**
|
||||
* Value object for AD_Menu.
|
||||
* <br/>
|
||||
* Use by {@link GlobalSearch} and {@link MenuSearchController}.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class MenuItem {
|
||||
|
||||
private String label;
|
||||
private String description;
|
||||
private String image;
|
||||
/** report, process, workflow, form, info or window **/
|
||||
private String type;
|
||||
/** Corresponding {@link Treeitem} or {@link DefaultTreeNode} **/
|
||||
private Object data;
|
||||
|
||||
/**
|
||||
*
|
||||
* default constructor
|
||||
*/
|
||||
public MenuItem() {
|
||||
}
|
||||
|
|
|
@ -55,41 +55,60 @@ import org.zkoss.zul.Textbox;
|
|||
import org.zkoss.zul.Tree;
|
||||
import org.zkoss.zul.Treechildren;
|
||||
import org.zkoss.zul.Treeitem;
|
||||
import org.zkoss.zul.Treerow;
|
||||
import org.zkoss.zul.Vlayout;
|
||||
import org.zkoss.zul.impl.LabelElement;
|
||||
import org.zkoss.zul.impl.LabelImageElement;
|
||||
|
||||
/**
|
||||
* Controller for search on AD_Menu records.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class MenuSearchController implements EventListener<Event>{
|
||||
|
||||
/** Component attribute to hold reference of {@link MTreeNode} **/
|
||||
public static final String M_TREE_NODE_ATTR = "MTreeNode";
|
||||
|
||||
/** font icon sclass for already added to favourite menu item **/
|
||||
private static final String Z_ICON_STAR_O = "z-icon-star-o";
|
||||
/** font icon sclass for not yet added to favourite menu item **/
|
||||
private static final String Z_ICON_STAR = "z-icon-star";
|
||||
private static final String ON_SEARCH_ECHO = "onSearchEcho";
|
||||
private static final String ON_LOAD_MORE = "onLoadMore";
|
||||
private static final String ONSELECT_TIMESTAMP = "onselect.timestamp";
|
||||
/** Event echo from {@link #search(String)} to initiate search action **/
|
||||
private static final String ON_SEARCH_ECHO_EVENT = "onSearchEcho";
|
||||
/** Event to load all menu items into {@link #listbox}. Default is to load the first 50 only. **/
|
||||
private static final String ON_LOAD_MORE_EVENT = "onLoadMore";
|
||||
/** {@link Listitem} attribute to store the last timestamp of ON_CLICK or ON_SELECT event **/
|
||||
private static final String ONSELECT_TIMESTAMP_ATTR = "onselect.timestamp";
|
||||
/** name of star button **/
|
||||
private static final String STAR_BUTTON_NAME = "Star";
|
||||
/** name of new button **/
|
||||
private static final String NEW_BUTTON_NAME = "New";
|
||||
/** tree for AD_Menu **/
|
||||
private Tree tree;
|
||||
/** list box for menu items **/
|
||||
private Listbox listbox;
|
||||
/** model for all menu items **/
|
||||
private ListModelList<MenuItem> model;
|
||||
/** main layout component. parent of {@link #listbox}. **/
|
||||
private Vlayout layout;
|
||||
/** model for all menu items **/
|
||||
private ListModelList<MenuItem> fullModel;
|
||||
/** true when controller is handling event from Star/Favourite button **/
|
||||
private boolean inStarEvent;
|
||||
|
||||
/** Event post from {@link #selectTreeitem(Object, Boolean)} **/
|
||||
private static final String ON_POST_SELECT_TREEITEM_EVENT = "onPostSelectTreeitem";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param tree
|
||||
*/
|
||||
public MenuSearchController(Tree tree) {
|
||||
this.tree = tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate {@link #model} from {@link #tree}
|
||||
*/
|
||||
public void refreshModel() {
|
||||
final List<MenuItem> list = new ArrayList<MenuItem>();
|
||||
if (tree.getModel() == null) {
|
||||
|
@ -116,6 +135,11 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
}, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add treeNode to list
|
||||
* @param list
|
||||
* @param treeNode
|
||||
*/
|
||||
private void addTreeItem(List<MenuItem> list, DefaultTreeNode<?> treeNode) {
|
||||
MTreeNode mNode = (MTreeNode) treeNode.getData();
|
||||
if (!mNode.isLeaf())
|
||||
|
@ -129,6 +153,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
list.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param treeItem
|
||||
* @return true if treeItem is a folder
|
||||
*/
|
||||
private boolean isFolder(Treeitem treeItem) {
|
||||
List<Component> list = treeItem.getChildren();
|
||||
for (Component c : list) {
|
||||
|
@ -139,6 +167,11 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add treeItem to list
|
||||
* @param list
|
||||
* @param treeItem
|
||||
*/
|
||||
private void addTreeItem(List<MenuItem> list, Treeitem treeItem) {
|
||||
if (isFolder(treeItem))
|
||||
return;
|
||||
|
@ -158,6 +191,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
item.setType((String) treeItem.getAttribute(AbstractMenuPanel.MENU_TYPE_ATTRIBUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param treeItem
|
||||
* @return label for treeItem
|
||||
*/
|
||||
private String getLabel(Treeitem treeItem) {
|
||||
String label = treeItem.getLabel();
|
||||
if (label == null || label.trim().length() == 0)
|
||||
|
@ -172,6 +209,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param treeItem
|
||||
* @return image url or font icon sclass (start with z-icon)
|
||||
*/
|
||||
private String getImage(Treeitem treeItem) {
|
||||
String image = treeItem.getImage();
|
||||
if (image == null || image.trim().length() == 0)
|
||||
|
@ -189,6 +230,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return image != null ? image.intern() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #refreshModel()} and layout UI.
|
||||
* @param parent
|
||||
*/
|
||||
public void create(Component parent) {
|
||||
refreshModel();
|
||||
|
||||
|
@ -220,8 +265,8 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
ZKUpdateUtil.setWidth(listheader, "28px");
|
||||
listhead.appendChild(listheader);
|
||||
|
||||
layout.addEventListener(ON_SEARCH_ECHO, this);
|
||||
layout.addEventListener(ON_LOAD_MORE, this);
|
||||
layout.addEventListener(ON_SEARCH_ECHO_EVENT, this);
|
||||
layout.addEventListener(ON_LOAD_MORE_EVENT, this);
|
||||
updateListboxModel(model);
|
||||
|
||||
FavouriteController controller = FavouriteController.getInstance(Executions.getCurrent().getSession());
|
||||
|
@ -240,7 +285,7 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
} else if (Events.ON_CLICK.equals(event.getName())) {
|
||||
if (event.getTarget() instanceof ListItem) {
|
||||
ListItem item = (ListItem) event.getTarget();
|
||||
Long onSelect = (Long) item.getAttribute(ONSELECT_TIMESTAMP);
|
||||
Long onSelect = (Long) item.getAttribute(ONSELECT_TIMESTAMP_ATTR);
|
||||
if (onSelect == null) {
|
||||
onSelect(item, Boolean.FALSE);
|
||||
} else if (System.currentTimeMillis() - onSelect.longValue() > 1000) {
|
||||
|
@ -276,9 +321,9 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
inStarEvent = false;
|
||||
}
|
||||
}
|
||||
} else if (event.getName().equals(ON_SEARCH_ECHO)) {
|
||||
} else if (event.getName().equals(ON_SEARCH_ECHO_EVENT)) {
|
||||
onSearchEcho((String) event.getData());
|
||||
} else if (event.getName().equals(ON_LOAD_MORE)) {
|
||||
} else if (event.getName().equals(ON_LOAD_MORE_EVENT)) {
|
||||
loadMore();
|
||||
}
|
||||
}
|
||||
|
@ -297,13 +342,19 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
listbox.setModel(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo {@link #ON_LOAD_MORE_EVENT} if selected is of type "...".
|
||||
* Otherwise delegate to {@link #selectTreeitem(Object, Boolean)}.
|
||||
* @param selected
|
||||
* @param newRecord true if event is originated from new record button
|
||||
*/
|
||||
private void onSelect(ListItem selected, Boolean newRecord) {
|
||||
MenuItem item = selected.getValue();
|
||||
if (item == null) return;
|
||||
if ("...".equals(item.getType())) {
|
||||
selected.setAttribute(ONSELECT_TIMESTAMP, System.currentTimeMillis());
|
||||
selected.setAttribute(ONSELECT_TIMESTAMP_ATTR, System.currentTimeMillis());
|
||||
Clients.showBusy(selected, null);
|
||||
Events.echoEvent(ON_LOAD_MORE, layout, null);
|
||||
Events.echoEvent(ON_LOAD_MORE_EVENT, layout, null);
|
||||
} else {
|
||||
if (newRecord) {
|
||||
Treeitem ti = (Treeitem)item.getData();
|
||||
|
@ -312,10 +363,14 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
newRecord = false;
|
||||
}
|
||||
selectTreeitem(item.getData(), newRecord);
|
||||
selected.setAttribute(ONSELECT_TIMESTAMP, System.currentTimeMillis());
|
||||
selected.setAttribute(ONSELECT_TIMESTAMP_ATTR, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load {@link #fullModel} to {@link #listbox}.
|
||||
* Only first 50 loaded to {@link #listbox} initially.
|
||||
*/
|
||||
private void loadMore() {
|
||||
ListModel<MenuItem> listModel = listbox.getModel();
|
||||
ListModelList<MenuItem> lml = (ListModelList<MenuItem>) listModel;
|
||||
|
@ -327,6 +382,11 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
Clients.scrollIntoView(listbox.getSelectedItem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #select(Treeitem)} and post {@link #ON_POST_SELECT_TREEITEM_EVENT} event.
|
||||
* @param node {@link Treeitem} or {@link DefaultTreeNode}
|
||||
* @param newRecord
|
||||
*/
|
||||
private void selectTreeitem(Object node, Boolean newRecord) {
|
||||
if (Executions.getCurrent().getAttribute(listbox.getUuid()+".selectTreeitem") != null)
|
||||
return;
|
||||
|
@ -350,6 +410,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure all parent node is open and ensure tree selected item is selectedItem
|
||||
* @param selectedItem
|
||||
*/
|
||||
private void select(Treeitem selectedItem) {
|
||||
Treeitem parent = selectedItem.getParentItem();
|
||||
while (parent != null) {
|
||||
|
@ -361,6 +425,11 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
selectedItem.getTree().setSelectedItem(selectedItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link #ON_POST_SELECT_TREEITEM_EVENT} event.
|
||||
* Post ON_CLICK event to link ({@link A} or {@link Treerow}).
|
||||
* @param newRecord
|
||||
*/
|
||||
private void onPostSelectTreeitem(Boolean newRecord) {
|
||||
Event event = null;
|
||||
if (tree.getSelectedItem().getTreerow().getFirstChild().getFirstChild() instanceof A)
|
||||
|
@ -374,11 +443,19 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
Events.postEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo {@link #ON_SEARCH_ECHO_EVENT} to initial search with value.
|
||||
* @param value
|
||||
*/
|
||||
public void search(String value) {
|
||||
listbox.setModel((ListModel<?>)null);
|
||||
Events.echoEvent(ON_SEARCH_ECHO, layout, value);
|
||||
Events.echoEvent(ON_SEARCH_ECHO_EVENT, layout, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link #ON_SEARCH_ECHO_EVENT} event.
|
||||
* @param value
|
||||
*/
|
||||
public void onSearchEcho(String value) {
|
||||
ListModelList<MenuItem> newModel = null;
|
||||
if (Util.isEmpty(value)) {
|
||||
|
@ -391,6 +468,12 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
updateListboxModel(newModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update {@link #listbox} with newModel.
|
||||
* If newModel has > 50 items, only first 50 is loaded into {@link #listbox}.
|
||||
* User has to click the load more link (...) to load the rest of the items into {@link #listbox}.
|
||||
* @param newModel
|
||||
*/
|
||||
private void updateListboxModel(ListModelList<MenuItem> newModel) {
|
||||
fullModel = null;
|
||||
if (newModel.size() > 50) {
|
||||
|
@ -406,10 +489,20 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
listbox.setModel(newModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to help filter menu items with a filter value.
|
||||
*/
|
||||
private class MenuListComparator implements Comparator<MenuItem> {
|
||||
|
||||
/**
|
||||
* Text to filter menu items by label.
|
||||
* Use startsWith if length of compare is < 3, otherwise use contains for filter.
|
||||
*/
|
||||
private String compare;
|
||||
|
||||
/**
|
||||
* @param compare filter text
|
||||
*/
|
||||
private MenuListComparator(String compare) {
|
||||
this.compare = Util.deleteAccents(compare.toLowerCase().trim());
|
||||
}
|
||||
|
@ -431,6 +524,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* select ListItem that comes before the current selected ListItem.
|
||||
* @return new selected {@link MenuItem}
|
||||
*/
|
||||
public MenuItem selectPrior() {
|
||||
int i = listbox.getSelectedIndex();
|
||||
if (i > 0) {
|
||||
|
@ -444,6 +541,10 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* select ListItem that comes after the current selected ListItem.
|
||||
* @return new selected {@link MenuItem}
|
||||
*/
|
||||
public MenuItem selectNext() {
|
||||
int i = listbox.getSelectedIndex();
|
||||
if (i < 0 && listbox.getItemCount() > 0) {
|
||||
|
@ -467,6 +568,11 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ON_OK event
|
||||
* @param textbox
|
||||
* @return true if there's partial or exact match for textbox value
|
||||
*/
|
||||
public boolean onOk(Textbox textbox) {
|
||||
String text = textbox.getText();
|
||||
if (Util.isEmpty(text))
|
||||
|
@ -498,6 +604,9 @@ public class MenuSearchController implements EventListener<Event>{
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ListitemRenderer} for {@link #listbox}
|
||||
*/
|
||||
private class MenuItemRenderer implements ListitemRenderer<MenuItem>, ListitemRendererExt {
|
||||
private static final String REMOVE_FROM_FAVOURITES_MSG = "RemoveFromFavourites";
|
||||
private static final String ADD_TO_FAVOURITES_MSG = "AddToFavourites";
|
||||
|
|
|
@ -78,7 +78,7 @@ import com.lowagie.text.pdf.PdfReader;
|
|||
import com.lowagie.text.pdf.PdfWriter;
|
||||
|
||||
/**
|
||||
* Dialog to Start process or report.
|
||||
* Embedded Dialog to Start process or report.
|
||||
* Displays information about the process
|
||||
* and lets the user decide to start it
|
||||
* and displays results (optionally print them).
|
||||
|
@ -90,30 +90,42 @@ import com.lowagie.text.pdf.PdfWriter;
|
|||
public class ProcessDialog extends AbstractProcessDialog implements EventListener<Event>, IHelpContext
|
||||
{
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -6728929130788829223L;
|
||||
|
||||
public static final String ON_INITIAL_FOCUS_EVENT = "onInitialFocus";
|
||||
|
||||
private static final String ON_OK_ECHO = "onOkEcho";
|
||||
/**
|
||||
* Event echo form {@link #onOk()} to defer execution of {@link #onOk()}.
|
||||
* Execution is defer to happens after the dismiss of modal dialog (usually info window) blocking parameter panel.
|
||||
*/
|
||||
private static final String ON_OK_ECHO_EVENT = "onOkEcho";
|
||||
|
||||
/** Logger */
|
||||
private static final CLogger log = CLogger.getCLogger(ProcessDialog.class);
|
||||
//
|
||||
|
||||
/** message from {@link ProcessInfoLog} **/
|
||||
private Table logMessageTable;
|
||||
/** record ids from {@link ProcessInfo} **/
|
||||
private int[] m_ids = null;
|
||||
|
||||
/** true if dialog is showing process parameters **/
|
||||
private boolean isParameterPage = true;
|
||||
private Mask mask;
|
||||
/** layout for process execution result **/
|
||||
private HtmlBasedComponent resultPanelLayout;
|
||||
/** process message content of {@link #resultPanelLayout} **/
|
||||
private HtmlBasedComponent messageResultContent;
|
||||
/** process log content of {@link #resultPanelLayout}, host {@link #logMessageTable} **/
|
||||
private HtmlBasedComponent infoResultContent;
|
||||
|
||||
/** Window No */
|
||||
private int m_WindowNo = -1;
|
||||
/** timestamp of previous key event **/
|
||||
private long prevKeyEventTime = 0;
|
||||
/**
|
||||
* Previous key event. use together with {@link #prevKeyEventTime} to detect double firing of key event from browser.
|
||||
*/
|
||||
private KeyEvent prevKeyEvent;
|
||||
|
||||
/**
|
||||
|
@ -134,7 +146,7 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
*/
|
||||
public ProcessDialog (int AD_Process_ID, boolean isSOTrx, String predefinedContextVariables)
|
||||
{
|
||||
log.info("Process=" + AD_Process_ID );
|
||||
if (log.isLoggable(Level.INFO)) log.info("Process=" + AD_Process_ID );
|
||||
m_WindowNo = SessionManager.getAppDesktop().registerWindow(this);
|
||||
this.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_WindowNo);
|
||||
Env.setContext(Env.getCtx(), m_WindowNo, "IsSOTrx", isSOTrx ? "Y" : "N");
|
||||
|
@ -145,7 +157,7 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
querySaved();
|
||||
addEventListener(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, this);
|
||||
addEventListener(ON_INITIAL_FOCUS_EVENT, this);
|
||||
addEventListener(ON_OK_ECHO, this);
|
||||
addEventListener(ON_OK_ECHO_EVENT, this);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
|
@ -189,6 +201,7 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
SessionManager.getAppDesktop().closeWindow(getWindowNo());
|
||||
}// dispose
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
Component component = event.getTarget();
|
||||
|
||||
|
@ -198,7 +211,7 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
super.onEvent(event);
|
||||
|
||||
onOk();
|
||||
} else if (event.getName().equals(ON_OK_ECHO)) {
|
||||
} else if (event.getName().equals(ON_OK_ECHO_EVENT)) {
|
||||
onOk();
|
||||
}else if (bCancel.equals(component)){
|
||||
super.onEvent(event);
|
||||
|
@ -236,12 +249,15 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ON_Click event from {@link #bOK}
|
||||
*/
|
||||
private void onOk() {
|
||||
if (isParameterPage)
|
||||
{
|
||||
if (getParameterPanel().isWaitingForDialog())
|
||||
{
|
||||
Events.echoEvent(ON_OK_ECHO, this, null);
|
||||
Events.echoEvent(ON_OK_ECHO_EVENT, this, null);
|
||||
return;
|
||||
}
|
||||
startProcess();
|
||||
|
@ -250,6 +266,10 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle shortcut key event
|
||||
* @param keyEvent
|
||||
*/
|
||||
private void onCtrlKeyEvent(KeyEvent keyEvent) {
|
||||
if (keyEvent.isAltKey() && keyEvent.getKeyCode() == 0x58) { // Alt-X
|
||||
if (m_WindowNo > 0) {
|
||||
|
@ -261,6 +281,10 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle on click event for record link.
|
||||
* @param btn
|
||||
*/
|
||||
private void doOnClick(A btn) {
|
||||
int Record_ID = 0;
|
||||
int AD_Table_ID =0;
|
||||
|
@ -273,7 +297,6 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
|
||||
if (Record_ID > 0 && AD_Table_ID > 0) {
|
||||
|
||||
AEnv.zoom(AD_Table_ID, Record_ID);
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +309,9 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
LayoutUtils.openOverlappedWindow(this, progressWindow, "middle_center");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return in progress mask
|
||||
*/
|
||||
private Div getMask() {
|
||||
if (mask == null) {
|
||||
mask = new Mask();
|
||||
|
@ -293,9 +319,14 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* show in progress mask
|
||||
* @param window
|
||||
*/
|
||||
private void showBusyMask(Window window) {
|
||||
if (getParent() != null) {
|
||||
getParent().appendChild(getMask());
|
||||
//to prevent focus to components beneath the in progress mask (see canActivate in web/js/org/idempiere/commons/window.js)
|
||||
StringBuilder script = new StringBuilder("(function(){let w=zk.Widget.$('#");
|
||||
script.append(getParent().getUuid()).append("');");
|
||||
if (window != null) {
|
||||
|
@ -308,6 +339,9 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* close in progress mask
|
||||
*/
|
||||
private void hideBusyMask()
|
||||
{
|
||||
if (mask != null && mask.getParent() != null) {
|
||||
|
@ -333,6 +367,9 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
swithToFinishScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to process execution result panel.
|
||||
*/
|
||||
protected void swithToFinishScreen() {
|
||||
ProcessInfo pi = getProcessInfo();
|
||||
ProcessInfoUtil.setLogFromDB(pi);
|
||||
|
@ -375,6 +412,10 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
Clients.response(new AuEcho(this, "onAfterProcess", null));
|
||||
}
|
||||
|
||||
/**
|
||||
* layout process execution result panel
|
||||
* @param topParameterLayout
|
||||
*/
|
||||
private void layoutResultPanel (HtmlBasedComponent topParameterLayout){
|
||||
if (resultPanelLayout == null){
|
||||
resultPanelLayout = new Vlayout();
|
||||
|
@ -388,11 +429,21 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* replace oldComponent with newComponent
|
||||
* @param newComponent
|
||||
* @param oldComponent
|
||||
*/
|
||||
protected void replaceComponent(HtmlBasedComponent newComponent, HtmlBasedComponent oldComponent) {
|
||||
oldComponent.getParent().insertBefore(newComponent, oldComponent);
|
||||
oldComponent.detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* append m_logs content to {@link #logMessageTable}
|
||||
* @param m_logs
|
||||
* @param infoResultContent
|
||||
*/
|
||||
private void appendRecordLogInfo(ProcessInfoLog[] m_logs, HtmlBasedComponent infoResultContent) {
|
||||
if (m_logs == null)
|
||||
return;
|
||||
|
@ -466,9 +517,11 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
tr.appendChild(td);
|
||||
}
|
||||
}
|
||||
//messageDiv.appendChild(logMessageTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move back from process execution result panel to process parameter panel
|
||||
*/
|
||||
private void restart() {
|
||||
replaceComponent (topParameterLayout, resultPanelLayout);
|
||||
|
||||
|
@ -500,6 +553,9 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle onAfterProcess event echo from {@link #swithToFinishScreen()}
|
||||
*/
|
||||
public void onAfterProcess()
|
||||
{
|
||||
//
|
||||
|
@ -510,15 +566,15 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Optional Processing Task
|
||||
/**
|
||||
* Optional after/post process execution task
|
||||
*/
|
||||
private boolean afterProcessTask()
|
||||
{
|
||||
// something to do?
|
||||
if (m_ids != null && m_ids.length > 0)
|
||||
{
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
// Print invoices
|
||||
if (getAD_Process_ID() == PROCESS_C_INVOICE_GENERATE)
|
||||
{
|
||||
|
@ -538,7 +594,7 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
return false;
|
||||
} // afterProcessTask
|
||||
|
||||
/**************************************************************************
|
||||
/**
|
||||
* Print Shipments
|
||||
*/
|
||||
private void printShipments()
|
||||
|
@ -557,8 +613,11 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
});
|
||||
} // printInvoices
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle onPrintShipments event echo by {@link #printShipments()}
|
||||
*/
|
||||
public void onPrintShipments()
|
||||
{
|
||||
// Loop through all items
|
||||
|
@ -649,8 +708,11 @@ public class ProcessDialog extends AbstractProcessDialog implements EventListene
|
|||
}
|
||||
}
|
||||
});
|
||||
} // printInvoices
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle onPrintInvoices event echo by {@link #printInvoices()}
|
||||
*/
|
||||
public void onPrintInvoices()
|
||||
{
|
||||
// Loop through all items
|
||||
|
|
|
@ -48,15 +48,22 @@ import org.zkoss.zk.ui.event.Events;
|
|||
public class ProcessModalDialog extends AbstractProcessDialog implements EventListener<Event>, DialogEvents
|
||||
{
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -6227339628038418701L;
|
||||
|
||||
private static final String ON_OK_ECHO = "onOkEcho";
|
||||
/**
|
||||
* Event echo form {@link #onOk()} to defer execution of {@link #onOk()}.
|
||||
* Execution is defer to happens after the dismiss of modal dialog (usually info window) blocking parameter panel.
|
||||
*/
|
||||
private static final String ON_OK_ECHO_EVENT = "onOkEcho";
|
||||
|
||||
/** Logger */
|
||||
private static final CLogger log = CLogger.getCLogger(ProcessModalDialog.class);
|
||||
//
|
||||
/**
|
||||
* Store screen orientation from last onClientInfo event.
|
||||
* Use to detect change of screen orientation and adapt layout accordingly.
|
||||
*/
|
||||
private String orientation;
|
||||
|
||||
/**
|
||||
|
@ -172,10 +179,17 @@ public class ProcessModalDialog extends AbstractProcessDialog implements EventLi
|
|||
{
|
||||
log.log(Level.SEVERE, "", ex);
|
||||
}
|
||||
addEventListener(ON_OK_ECHO, this);
|
||||
addEventListener(ON_OK_ECHO_EVENT, this);
|
||||
addEventListener(Events.ON_CANCEL, e -> onCancel());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WindowNo
|
||||
* @param AD_Process_ID
|
||||
* @param tableId
|
||||
* @param recordId
|
||||
* @param autoStart
|
||||
*/
|
||||
public ProcessModalDialog (int WindowNo, int AD_Process_ID, int tableId, int recordId, boolean autoStart)
|
||||
{
|
||||
this(null, WindowNo, AD_Process_ID, tableId, recordId, autoStart);
|
||||
|
@ -265,12 +279,13 @@ public class ProcessModalDialog extends AbstractProcessDialog implements EventLi
|
|||
/**
|
||||
* handle events
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
Component component = event.getTarget();
|
||||
if (component.equals(bOK)) {
|
||||
super.onEvent(event);
|
||||
onOk();
|
||||
} else if (event.getName().equals(ON_OK_ECHO)) {
|
||||
} else if (event.getName().equals(ON_OK_ECHO_EVENT)) {
|
||||
onOk();
|
||||
} else if (component.equals(bCancel)) {
|
||||
super.onEvent(event);
|
||||
|
@ -280,14 +295,20 @@ public class ProcessModalDialog extends AbstractProcessDialog implements EventLi
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ON_Click event from {@link #bCancel}
|
||||
*/
|
||||
private void onCancel() {
|
||||
cancelProcess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ON_Click event from {@link #bOK}
|
||||
*/
|
||||
private void onOk() {
|
||||
if (getParameterPanel().isWaitingForDialog())
|
||||
{
|
||||
Events.echoEvent(ON_OK_ECHO, this, null);
|
||||
Events.echoEvent(ON_OK_ECHO_EVENT, this, null);
|
||||
return;
|
||||
}
|
||||
if(fPrintFormat != null && fPrintFormat.getValue() != null) {
|
||||
|
@ -302,6 +323,9 @@ public class ProcessModalDialog extends AbstractProcessDialog implements EventLi
|
|||
startProcess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client info event from browser
|
||||
*/
|
||||
protected void onClientInfo() {
|
||||
if (getPage() != null) {
|
||||
String newOrientation = ClientInfo.get().orientation;
|
||||
|
|
|
@ -84,9 +84,9 @@ import org.zkoss.zul.impl.InputElement;
|
|||
import org.zkoss.zul.impl.XulElement;
|
||||
|
||||
/**
|
||||
* Process Parameter Panel, based on existing ProcessParameter dialog. -
|
||||
* Embedded in ProcessDialog - checks, if parameters exist and inquires and
|
||||
* saves them
|
||||
* Process Parameter Panel.
|
||||
* Embedded in {@link ProcessDialog} and {@link ProcessModalDialog}.
|
||||
* Capture parameters input, validate and save to DB.
|
||||
*
|
||||
* @author Low Heng Sin
|
||||
* @version 2006-12-01
|
||||
|
@ -94,17 +94,18 @@ import org.zkoss.zul.impl.XulElement;
|
|||
public class ProcessParameterPanel extends Panel implements
|
||||
ValueChangeListener, IProcessParameter, EventListener<Event> {
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = -6099317911368929787L;
|
||||
|
||||
/** Event post from {@link #valueChange(ValueChangeEvent)} **/
|
||||
private static final String ON_POST_EDITOR_VALUE_CHANGE_EVENT = "onPostEditorValueChange";
|
||||
|
||||
/**
|
||||
* Dynamic generated Parameter panel.
|
||||
*
|
||||
* @param WindowNo
|
||||
* window
|
||||
* @param pi
|
||||
* process info
|
||||
* @param WindowNo register window number
|
||||
* @param pi process info
|
||||
*/
|
||||
public ProcessParameterPanel(int WindowNo, ProcessInfo pi) {
|
||||
this(WindowNo, 0, pi);
|
||||
|
@ -113,12 +114,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
/**
|
||||
* Dynamic generated Parameter panel.
|
||||
*
|
||||
* @param WindowNo
|
||||
* window
|
||||
* @param tabNo
|
||||
* tabNo
|
||||
* @param pi
|
||||
* process info
|
||||
* @param WindowNo register window number
|
||||
* @param tabNo tabNo
|
||||
* @param pi process info
|
||||
*/
|
||||
public ProcessParameterPanel(int WindowNo,int tabNo, ProcessInfo pi) {
|
||||
//
|
||||
|
@ -130,9 +128,12 @@ public class ProcessParameterPanel extends Panel implements
|
|||
//
|
||||
initComponent();
|
||||
addEventListener("onDynamicDisplay", this);
|
||||
addEventListener("onPostEditorValueChange", this);
|
||||
addEventListener(ON_POST_EDITOR_VALUE_CHANGE_EVENT, this);
|
||||
} // ProcessParameterPanel
|
||||
|
||||
/**
|
||||
* Layout UI
|
||||
*/
|
||||
private void initComponent() {
|
||||
centerPanel = GridFactory.newGridLayout();
|
||||
this.appendChild(centerPanel);
|
||||
|
@ -151,27 +152,36 @@ public class ProcessParameterPanel extends Panel implements
|
|||
private int m_WindowNo;
|
||||
private int m_TabNo;
|
||||
private ProcessInfo m_processInfo;
|
||||
// AD_Window of window below this dialog in case show parameter dialog panel
|
||||
/** AD_Window_ID if process dialog is launch by AD_Window **/
|
||||
private int m_AD_Window_ID = 0;
|
||||
// infoWindowID of infoWindow below this dialog in case call process from infoWindow
|
||||
/** Info_Window_ID if process dialog is launch by Info Window **/
|
||||
private int m_InfoWindowID = 0;
|
||||
/** Logger */
|
||||
private static final CLogger log = CLogger
|
||||
.getCLogger(ProcessParameterPanel.class);
|
||||
|
||||
//
|
||||
/** parameter editor list **/
|
||||
private ArrayList<WEditor> m_wEditors = new ArrayList<WEditor>();
|
||||
private ArrayList<WEditor> m_wEditors2 = new ArrayList<WEditor>(); // for ranges
|
||||
/** to parameter editor list for range parameter **/
|
||||
private ArrayList<WEditor> m_wEditors2 = new ArrayList<WEditor>();
|
||||
/** parameter field list **/
|
||||
private ArrayList<GridField> m_mFields = new ArrayList<GridField>();
|
||||
/** to parameter field list for range parameter **/
|
||||
private ArrayList<GridField> m_mFields2 = new ArrayList<GridField>();
|
||||
private ArrayList<Space> m_separators = new ArrayList<Space>();
|
||||
/** all rows of {@link #centerPanel} **/
|
||||
private ArrayList<Row> m_Rows = new ArrayList<Row>();
|
||||
//
|
||||
/** layout grid for parameter fields **/
|
||||
private Grid centerPanel = null;
|
||||
/** Group Name:Rows for parameter field **/
|
||||
private Map<String, List<Row>> fieldGroupContents = new HashMap<String, List<Row>>();
|
||||
/** Group Name:Rows for group header **/
|
||||
private Map<String, List<org.zkoss.zul.Row>> fieldGroupHeaders = new HashMap<String, List<org.zkoss.zul.Row>>();
|
||||
/** rows of current rendering group **/
|
||||
private ArrayList<Row> rowList;
|
||||
/** all groups of field type collapsible or tab **/
|
||||
private List<Group> allCollapsibleGroups = new ArrayList<Group>();
|
||||
/** current rendering group **/
|
||||
private Group currentGroup;
|
||||
|
||||
/**
|
||||
|
@ -186,12 +196,12 @@ public class ProcessParameterPanel extends Panel implements
|
|||
} // dispose
|
||||
|
||||
/**
|
||||
* Read Fields to display
|
||||
* Render all visible fields
|
||||
*
|
||||
* @return true if loaded OK
|
||||
*/
|
||||
public boolean init() {
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
// ASP
|
||||
MClient client = MClient.get(Env.getCtx());
|
||||
|
@ -385,12 +395,13 @@ public class ProcessParameterPanel extends Panel implements
|
|||
} // initDialog
|
||||
|
||||
/**
|
||||
* Create Field. - creates Fields and adds it to m_mFields list - creates
|
||||
* Editor and adds it to m_vEditors list Handeles Ranges by adding
|
||||
* additional mField/vEditor.
|
||||
* Create editor and adds it to {@link #m_wEditors}.
|
||||
* <br/>
|
||||
* For range type field, create the to field and add it to {@link #m_mFields2} and
|
||||
* create the to editor and adds it to {@link #m_wEditors2}.
|
||||
* <p>
|
||||
* mFields are used for default value and mandatory checking; vEditors are
|
||||
* used to retrieve the value (no data binding)
|
||||
* mField is used for default value and mandatory checking and editor is
|
||||
* used to capture input value from user (no data binding).
|
||||
*
|
||||
* @param voF GridFieldVO
|
||||
* @param mField
|
||||
|
@ -403,7 +414,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
editor.getComponent().addEventListener(Events.ON_FOCUS, this);
|
||||
editor.addValueChangeListener(this);
|
||||
editor.dynamicDisplay();
|
||||
// MField => VEditor - New Field value to be updated to editor
|
||||
// MField => editor - New Field value to be updated to editor
|
||||
mField.addPropertyChangeListener(editor);
|
||||
// Set Default
|
||||
Object defaultObject = mField.getDefaultForPanel();
|
||||
|
@ -446,6 +457,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
Div box = new Div();
|
||||
box.setStyle("display: flex; align-items: center;");
|
||||
ZKUpdateUtil.setWidth(box, "100%");
|
||||
//create to field and editor
|
||||
if (voF.isRange) {
|
||||
box.appendChild(editor.getComponent());
|
||||
ZKUpdateUtil.setWidth((HtmlBasedComponent) editor.getComponent(), "49%");
|
||||
|
@ -492,6 +504,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
m_mFields2.add(null);
|
||||
m_wEditors2.add(null);
|
||||
m_separators.add(null);
|
||||
//add not in support for multi selection field
|
||||
if(DisplayType.isChosenMultipleSelection(mField.getDisplayType())) {
|
||||
Button bNegate = ButtonFactory.createButton("", null, null);
|
||||
bNegate.setTooltiptext(Msg.translate(Env.getCtx(), "IncludeSelectedValues"));
|
||||
|
@ -507,6 +520,11 @@ public class ProcessParameterPanel extends Panel implements
|
|||
row.appendChild(box);
|
||||
} // createField
|
||||
|
||||
/**
|
||||
* set place holder message
|
||||
* @param editor
|
||||
* @param msg
|
||||
*/
|
||||
private void setEditorPlaceHolder(WEditor editor, String msg) {
|
||||
Component c = editor.getComponent();
|
||||
if (c instanceof InputElement) {
|
||||
|
@ -528,11 +546,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
* @return true if parameters are valid
|
||||
*/
|
||||
public boolean validateParameters() {
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
/**
|
||||
* Mandatory fields see - MTable.getMandatory
|
||||
*/
|
||||
//mandatory fields validation
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int size = m_mFields.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
@ -577,6 +593,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
return false;
|
||||
}
|
||||
|
||||
/** call {@link IProcessParameterListener} validate(ProcessParameterPanel) **/
|
||||
if (m_processInfo.getAD_Process_ID() > 0) {
|
||||
String className = MProcess.get(Env.getCtx(), m_processInfo.getAD_Process_ID()).getClassname();
|
||||
List<IProcessParameterListener> listeners = Extensions.getProcessParameterListeners(className, null);
|
||||
|
@ -592,12 +609,13 @@ public class ProcessParameterPanel extends Panel implements
|
|||
return true;
|
||||
} // validateParameters
|
||||
|
||||
/*
|
||||
/**
|
||||
* load parameters from saved instance
|
||||
* @param instance
|
||||
*/
|
||||
public boolean loadParameters(MPInstance instance)
|
||||
{
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
MPInstancePara[] params = instance.getParameters();
|
||||
for (int j = 0; j < m_mFields.size(); j++)
|
||||
|
@ -688,12 +706,13 @@ public class ProcessParameterPanel extends Panel implements
|
|||
return true;
|
||||
} // loadParameters
|
||||
|
||||
/*
|
||||
/**
|
||||
* Load parameters from Process Info
|
||||
* @param pi
|
||||
*/
|
||||
public boolean loadParametersFromProcessInfo(ProcessInfo pi)
|
||||
{
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
ProcessInfoParameter[] params = pi.getParameter();
|
||||
for (int j = 0; j < m_mFields.size(); j++)
|
||||
|
@ -742,12 +761,12 @@ public class ProcessParameterPanel extends Panel implements
|
|||
} // loadParameters
|
||||
|
||||
/**
|
||||
* Save Parameter values
|
||||
* Save parameter values to {@link MPInstancePara}.
|
||||
*
|
||||
* @return true if parameters saved
|
||||
*/
|
||||
public boolean saveParameters() {
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
if (!validateParameters())
|
||||
return false;
|
||||
|
@ -839,21 +858,19 @@ public class ProcessParameterPanel extends Panel implements
|
|||
} // saveParameters
|
||||
|
||||
/**
|
||||
* Get Parameter values without saving
|
||||
* Get parameter values from editors without saving to DB.
|
||||
*
|
||||
* @return list of parameter values
|
||||
* @return MPInstancePara[], list of parameter values.
|
||||
*/
|
||||
public MPInstancePara[] getParameters() {
|
||||
log.config("");
|
||||
if (log.isLoggable(Level.CONFIG)) log.config("");
|
||||
|
||||
if (!validateParameters())
|
||||
return new MPInstancePara[0];
|
||||
|
||||
List<MPInstancePara> paras = new ArrayList<MPInstancePara>();
|
||||
|
||||
/**********************************************************************
|
||||
* Save Now
|
||||
*/
|
||||
/** create MPInstancePara from editors and add to paras (without saving MPInstancePara to DB) **/
|
||||
for (int i = 0; i < m_mFields.size(); i++) {
|
||||
// Get Values
|
||||
WEditor editor = (WEditor) m_wEditors.get(i);
|
||||
|
@ -928,12 +945,10 @@ public class ProcessParameterPanel extends Panel implements
|
|||
|
||||
|
||||
/**
|
||||
* Editor Listener
|
||||
* Editor value change listener.
|
||||
*
|
||||
* @param evt
|
||||
* ValueChangeEvent
|
||||
* @param evt ValueChangeEvent
|
||||
*/
|
||||
|
||||
public void valueChange(ValueChangeEvent evt) {
|
||||
String propName = evt.getPropertyName();
|
||||
if (evt.getSource() instanceof WEditor) {
|
||||
|
@ -947,7 +962,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
processDependencies (changedField);
|
||||
// future processCallout (changedField);
|
||||
}
|
||||
Events.postEvent("onPostEditorValueChange", this, evt.getSource());
|
||||
Events.postEvent(ON_POST_EDITOR_VALUE_CHANGE_EVENT, this, evt.getSource());
|
||||
}
|
||||
processNewValue(evt.getNewValue(), propName);
|
||||
}
|
||||
|
@ -955,6 +970,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
if (event.getName().equals(Events.ON_FOCUS)) {
|
||||
//update tooltip text inside desktop help panel.
|
||||
for (WEditor editor : m_wEditors)
|
||||
{
|
||||
if (editor.isComponentOfEditor(event.getTarget()))
|
||||
|
@ -976,7 +992,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
else if (event.getName().equals("onDynamicDisplay")) {
|
||||
dynamicDisplay();
|
||||
}
|
||||
else if (event.getName().equals("onPostEditorValueChange")) {
|
||||
else if (event.getName().equals(ON_POST_EDITOR_VALUE_CHANGE_EVENT)) {
|
||||
WEditor editor = (WEditor)event.getData();
|
||||
onPostEditorValueChange(editor);
|
||||
if(editor.getComponent() != null) {
|
||||
|
@ -996,6 +1012,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
else if (event.getName().equals(Events.ON_CLICK)) {
|
||||
if(event.getTarget() instanceof Button) {
|
||||
//from not in button of multi selection field
|
||||
Button bNegate = (Button)event.getTarget();
|
||||
boolean isSelected = !(boolean)bNegate.getAttribute("isSelected");
|
||||
if(isSelected) {
|
||||
|
@ -1013,6 +1030,12 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ON_POST_EDITOR_VALUE_CHANGE_EVENT event.
|
||||
* <br/>
|
||||
* Call {@link IProcessParameterListener#validate(ProcessParameterPanel)}.
|
||||
* @param editor
|
||||
*/
|
||||
private void onPostEditorValueChange(WEditor editor) {
|
||||
if (m_processInfo.getAD_Process_ID() > 0) {
|
||||
String className = MProcess.get(Env.getCtx(), m_processInfo.getAD_Process_ID()).getClassname();
|
||||
|
@ -1029,7 +1052,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
|
||||
/**
|
||||
* Evaluate Dependencies
|
||||
* Notify dependent fields.
|
||||
* @param changedField changed field
|
||||
*/
|
||||
private void processDependencies (GridField changedField)
|
||||
|
@ -1048,6 +1071,11 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
} // processDependencies
|
||||
|
||||
/**
|
||||
* Reset field value to null if field depends on columnName.
|
||||
* @param field
|
||||
* @param columnName column name of changed field
|
||||
*/
|
||||
private void verifyChangedField(GridField field, String columnName) {
|
||||
ArrayList<String> list = field.getDependentOn();
|
||||
if (list.contains(columnName)) {
|
||||
|
@ -1066,6 +1094,11 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new value from {@link #valueChange(ValueChangeEvent)}.
|
||||
* @param value
|
||||
* @param name
|
||||
*/
|
||||
private void processNewValue(Object value, String name) {
|
||||
if (value == null)
|
||||
value = new String("");
|
||||
|
@ -1086,6 +1119,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
Events.postEvent("onDynamicDisplay", this, (Object)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic update the UI state and properties of all fields.
|
||||
*/
|
||||
private void dynamicDisplay() {
|
||||
for (int i = 0; i < m_wEditors.size(); i++) {
|
||||
WEditor editor = m_wEditors.get(i);
|
||||
|
@ -1172,6 +1208,10 @@ public class ProcessParameterPanel extends Panel implements
|
|||
m_processInfo = processInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* focus to first visible field editor.
|
||||
* @return true if there is at least one visible field editor.
|
||||
*/
|
||||
public boolean focusToFirstEditor() {
|
||||
if (m_wEditors.isEmpty())
|
||||
return false;
|
||||
|
@ -1184,6 +1224,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param toFocus
|
||||
*/
|
||||
private void focusToEditor(WEditor toFocus) {
|
||||
Component c = toFocus.getComponent();
|
||||
if (c instanceof EditorBox) {
|
||||
|
@ -1211,7 +1254,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
|
||||
/**
|
||||
* Get parameter field value to editor by column name
|
||||
* Get parameter field to editor by column name
|
||||
* @param columnName
|
||||
* @return editor
|
||||
*/
|
||||
|
@ -1225,7 +1268,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
}
|
||||
|
||||
/**
|
||||
* @return true if editor is showing dialog awaiting user action
|
||||
* @return true if editor is showing dialog awaiting user action (usually info window).
|
||||
*/
|
||||
public boolean isWaitingForDialog() {
|
||||
for (int i = 0; i < m_mFields.size(); i++) {
|
||||
|
@ -1244,6 +1287,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field label ON_CLICK listener for {@link IZoomableEditor}.
|
||||
*/
|
||||
static class ZoomListener implements EventListener<Event> {
|
||||
|
||||
private IZoomableEditor searchEditor;
|
||||
|
@ -1261,6 +1307,9 @@ public class ProcessParameterPanel extends Panel implements
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return register window number.
|
||||
*/
|
||||
public int getWindowNo() {
|
||||
return m_WindowNo;
|
||||
}
|
||||
|
|
|
@ -70,14 +70,14 @@ import org.zkoss.zul.Center;
|
|||
import org.zkoss.zul.Div;
|
||||
|
||||
/**
|
||||
*
|
||||
* Drill assistant dialog
|
||||
* @author Igor Pojzl, Cloudempiere
|
||||
*
|
||||
*/
|
||||
public class WDrillReport extends Window implements EventListener<Event> {
|
||||
|
||||
/**
|
||||
*
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = 5143424676962140799L;
|
||||
|
||||
|
@ -88,10 +88,14 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
private static final String DRILL_REPORT_TABLE_NAME = "TableName";
|
||||
|
||||
private DrillReportCtl drillReportCtl;
|
||||
/** generated unique window name prefix **/
|
||||
private String winpref;
|
||||
|
||||
/** tabpanel for related table drill **/
|
||||
private Tabpanel tabPanel;
|
||||
/** tab for related table drill **/
|
||||
private Tab tableTab;
|
||||
/** true if {@link #tabPanel} loaded **/
|
||||
private boolean tablesLoaded = false;
|
||||
|
||||
private int windowNo = 0;
|
||||
|
@ -150,6 +154,10 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
td.appendChild(getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Header text
|
||||
* @return {@link Table}
|
||||
*/
|
||||
private Table getHeader()
|
||||
{
|
||||
Table table = new Table();
|
||||
|
@ -202,6 +210,10 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabbox with Drill Rules and Related Tables tab.
|
||||
* @return {@link Tabbox}
|
||||
*/
|
||||
private Tabbox getContent()
|
||||
{
|
||||
|
||||
|
@ -236,6 +248,14 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return tabbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table with links for all process and nested table for print formats for each process.
|
||||
* @param tabIndex
|
||||
* @param drillTables [AD_Process_ID,Process Name]
|
||||
* @param drillPrintFormatMap AD_Process_ID:[AD_Process_DrillRule_ID,Name]
|
||||
* @param isDrillProcessRule true for drill rules, false for related tables
|
||||
* @return {@link Table}
|
||||
*/
|
||||
private Table getTabContent(int tabIndex, KeyNamePair[] drillTables, HashMap<Integer, KeyNamePair[]> drillPrintFormatMap, boolean isDrillProcessRule)
|
||||
{
|
||||
Table table = new Table();
|
||||
|
@ -276,7 +296,6 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
td.appendChild(getTablesBox(tabIndex, drillTables));
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
|
||||
KeyNamePair drillTable = drillTables[i];
|
||||
|
||||
// tab
|
||||
|
@ -292,6 +311,15 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table with process name and print formats
|
||||
* @param drillTable [AD_Process_ID,Process Name]
|
||||
* @param tabIndex
|
||||
* @param groupIndex
|
||||
* @param drillPrintFormatMap AD_Process_ID:[AD_Process_DrillRule_ID,Name]
|
||||
* @param isDrillProcessRule
|
||||
* @return {@link Table}
|
||||
*/
|
||||
private Table getDrillTableBox(KeyNamePair drillTable, int tabIndex, int groupIndex, HashMap<Integer, KeyNamePair[]> drillPrintFormatMap, boolean isDrillProcessRule)
|
||||
{
|
||||
Table table = new Table();
|
||||
|
@ -325,11 +353,14 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
a.appendChild(new Text(".."));
|
||||
header.appendChild(a);
|
||||
|
||||
//[AD_Process_DrillRule_ID,Name]
|
||||
KeyNamePair[] drillRules = drillPrintFormatMap != null ? drillPrintFormatMap.get(drillTable.getKey()) : new KeyNamePair[]{findTablePrintFormat(drillTable)};
|
||||
for (int j = 0; j < drillRules.length; j++)
|
||||
{
|
||||
//(AD_Process_DrillRule_ID,Name) or (AD_PrintFormat_ID,Name)
|
||||
KeyNamePair drillRule = drillRules[j];
|
||||
|
||||
//[AD_PrintFormat_ID,Name]
|
||||
KeyNamePair[] printFormats = isDrillProcessRule ? drillReportCtl.getDrillProcessRulesPrintFormatMap(drillRule.getKey()) : new KeyNamePair[] {drillRule} ;
|
||||
|
||||
// create new Print Format
|
||||
|
@ -376,7 +407,10 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param drillTable KeyNamePair(AD_Process_ID,Process Name)
|
||||
* @return KeyNamePair(AD_PrintFormat_ID,Name)
|
||||
*/
|
||||
private KeyNamePair findTablePrintFormat(KeyNamePair drillTable) {
|
||||
|
||||
Integer printFormatID = new Query(Env.getCtx(), MPrintFormat.Table_Name, " AD_Table_ID = ? AND AD_Client_ID IN (0,?) ", null)
|
||||
|
@ -385,7 +419,12 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return new KeyNamePair((printFormatID != null && printFormatID > 0) ? printFormatID : 0, drillTable.getName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Link for process in drillTables
|
||||
* @param tabIndex
|
||||
* @param drillTables [AD_Process_ID,Process Name]
|
||||
* @return {@link Table}
|
||||
*/
|
||||
private Table getTablesBox(int tabIndex, KeyNamePair[] drillTables)
|
||||
{
|
||||
Table table = new Table();
|
||||
|
@ -436,6 +475,17 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link and description for print format.
|
||||
* @param drillPrintFormat KeyNamePair(AD_PrintFormat_ID,Name)
|
||||
* @param reportIndex
|
||||
* @param formatIndex
|
||||
* @param groupIndex
|
||||
* @param drillTable KeyNamePair(AD_Process_ID,Name)
|
||||
* @param drillRule KeyNamePair(AD_Process_DrillRule_ID,Name)
|
||||
* @param isSinglePrintFormat
|
||||
* @return {@link Tr}
|
||||
*/
|
||||
private Tr getPrintFormatBox(KeyNamePair drillPrintFormat, int reportIndex, int formatIndex, int groupIndex, KeyNamePair drillTable, KeyNamePair drillRule, boolean isSinglePrintFormat)
|
||||
{
|
||||
|
||||
|
@ -451,7 +501,6 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
H4 h4 = new H4();
|
||||
h4.appendChild(new Text(drillPrintFormat.getName()));
|
||||
|
||||
|
||||
td.appendChild(h4);
|
||||
a = new A();
|
||||
a.setHref("#"+winpref+"Rep"+reportIndex+"-"+groupIndex);
|
||||
|
@ -459,8 +508,6 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
a.appendChild(new Text(".."));
|
||||
td.appendChild(a);
|
||||
|
||||
|
||||
|
||||
td = new Td();
|
||||
td.setStyle("width: 10%");
|
||||
tr.appendChild(td);
|
||||
|
@ -495,7 +542,6 @@ public class WDrillReport extends Window implements EventListener<Event> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
td = new Td();
|
||||
td.setStyle("width: 60");
|
||||
tr.appendChild(td);
|
||||
|
|
|
@ -40,7 +40,8 @@ import org.zkoss.zk.ui.event.Event;
|
|||
import org.zkoss.zk.ui.event.EventListener;
|
||||
|
||||
/**
|
||||
* Ported from org.compiere.apps.ProcessCtl
|
||||
* Zk client controller for execution of process.
|
||||
*
|
||||
* @author hengsin
|
||||
* @contributor red1 IDEMPIERE-1711 with final review by Hengsin
|
||||
*
|
||||
|
@ -50,25 +51,28 @@ public class WProcessCtl extends AbstractProcessCtl {
|
|||
/** Logger */
|
||||
private static final CLogger log = CLogger.getCLogger(WProcessCtl.class);
|
||||
|
||||
/**
|
||||
* Call {@link #process(int, ProcessInfo, Trx, EventListener)}
|
||||
* @param WindowNo
|
||||
* @param pi
|
||||
* @param trx
|
||||
*/
|
||||
public static void process (int WindowNo, ProcessInfo pi, Trx trx)
|
||||
{
|
||||
process(WindowNo, pi, trx, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Control
|
||||
* <code>
|
||||
* - Get Instance ID
|
||||
* - Get Parameters
|
||||
* - execute (lock - start process - unlock)
|
||||
* </code>
|
||||
* Creates a ProcessCtl instance, which calls
|
||||
* lockUI and unlockUI if parent is a ASyncProcess
|
||||
* <br>
|
||||
* Open ProcessModalDialog to run process.
|
||||
* <pre>
|
||||
* - Create and save {@link MPInstance} if no pi.AD_PInstance_ID.
|
||||
* - Use {@link ProcessModalDialog} to capture process parameters and run process.
|
||||
* </pre>
|
||||
*
|
||||
* @param WindowNo window no
|
||||
* @param pi ProcessInfo process info
|
||||
* @param trx Transaction
|
||||
* @param listener listener for {@link ProcessModalDialog}
|
||||
*/
|
||||
public static void process (int WindowNo, ProcessInfo pi, Trx trx, EventListener<Event> listener)
|
||||
{
|
||||
|
@ -104,7 +108,6 @@ public class WProcessCtl extends AbstractProcessCtl {
|
|||
ProcessModalDialog para = new ProcessModalDialog(listener, WindowNo, pi, false);
|
||||
if (para.isValid())
|
||||
{
|
||||
//para.setWidth("500px");
|
||||
para.setVisible(true);
|
||||
|
||||
Object window = SessionManager.getAppDesktop().findWindow(WindowNo);
|
||||
|
@ -134,21 +137,18 @@ public class WProcessCtl extends AbstractProcessCtl {
|
|||
} // execute
|
||||
|
||||
/**
|
||||
* Async Process - Do it all.
|
||||
* <code>
|
||||
* - Get Instance ID
|
||||
* - Get Parameters
|
||||
* - execute (lock - start process - unlock)
|
||||
* </code>
|
||||
* Creates a ProcessCtl instance, which calls
|
||||
* lockUI and unlockUI if parent is a ASyncProcess
|
||||
* <br>
|
||||
* Called from ProcessDialog.actionPerformed
|
||||
* Save parameters and execute process.
|
||||
* <pre>
|
||||
* - Create and save {@link MPInstance} if no pi.AD_PInstance_ID.
|
||||
* - Call parameter.saveParameters ({@link IProcessParameter#saveParameters()}) to save process parameters.
|
||||
* - Save pi.getRecord_IDs() to T_Selections ({@link DB#createT_Selection(int, java.util.Collection, String)}).
|
||||
* - Call {@link WProcessCtl#run()} to execute process.
|
||||
* </pre>
|
||||
*
|
||||
* @param aProcessUI ASyncProcess and Container
|
||||
* @param aProcessUI {@link IProcessUI}
|
||||
* @param WindowNo window no
|
||||
* @param parameter Process Parameter Panel
|
||||
* @param pi ProcessInfo process info
|
||||
* @param pi {@link ProcessInfo}
|
||||
* @param trx Transaction
|
||||
*/
|
||||
public static void process(IProcessUI aProcessUI, int WindowNo, IProcessParameter parameter, ProcessInfo pi, Trx trx)
|
||||
|
|
|
@ -40,15 +40,15 @@ import org.zkoss.zul.Menuitem;
|
|||
import org.zkoss.zul.Menupopup;
|
||||
|
||||
/**
|
||||
* Base on org.compiere.print.AReport
|
||||
* Launch report for table (immediate or through popup menu, depends on number of print format discover
|
||||
* for AD_Table_ID and AD_Window_ID).
|
||||
* @author Low Heng Sin
|
||||
*
|
||||
*/
|
||||
public class WReport implements EventListener<Event> {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Call {@link #WReport(int, MQuery, Component, int)}
|
||||
* @param AD_Table_ID table
|
||||
* @param query query
|
||||
*/
|
||||
|
@ -58,11 +58,10 @@ public class WReport implements EventListener<Event> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Call {@link #WReport(int, MQuery, Component, int, String)}
|
||||
* @param AD_Table_ID table
|
||||
* @param query query
|
||||
* @param parent The invoking parent window
|
||||
* @param parent The invoking parent component
|
||||
* @param WindowNo The invoking parent window number
|
||||
*/
|
||||
public WReport (int AD_Table_ID, MQuery query, Component parent,
|
||||
|
@ -72,7 +71,8 @@ public class WReport implements EventListener<Event> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Launch report immediately (if only one print format found) or show menu popup
|
||||
* for the list of print formats discover for AD_Table_ID and AD_Window_ID (from WindowNo).
|
||||
*
|
||||
* @param AD_Table_ID table
|
||||
* @param query query
|
||||
|
@ -103,25 +103,26 @@ public class WReport implements EventListener<Event> {
|
|||
getPrintFormats (AD_Table_ID, AD_Window_ID);
|
||||
} // AReport
|
||||
|
||||
/** The Query */
|
||||
/** Query parameter **/
|
||||
private MQuery m_query;
|
||||
/** menu popup to show the list of print formats discover **/
|
||||
private Menupopup m_popup;
|
||||
/** The Option List */
|
||||
/** List of KeyNamePair(AD_PrintFormat_ID,Name) **/
|
||||
private List<KeyNamePair> m_list = new ArrayList<KeyNamePair>();
|
||||
/** Logger */
|
||||
/** Logger **/
|
||||
private static final CLogger log = CLogger.getCLogger(WReport.class);
|
||||
/** The parent window for locking/unlocking during process execution */
|
||||
Component parent;
|
||||
/** The parent window number */
|
||||
int WindowNo;
|
||||
/** The filter to apply to this report */
|
||||
/** The invoking parent component **/
|
||||
protected Component parent;
|
||||
/** The parent window number **/
|
||||
protected int WindowNo;
|
||||
/** The filter to apply to this report **/
|
||||
private String whereExtended;
|
||||
|
||||
/**
|
||||
* Get the Print Formats for the table.
|
||||
* Fill the list and the popup menu
|
||||
* Get Print Formats for table and window.
|
||||
* If there's only 1 print format found, call {@link #launchReport(KeyNamePair)}, otherwise call {@link #showPopup()}.
|
||||
* @param AD_Table_ID table
|
||||
* @param invoker component to display popup (optional)
|
||||
* @param AD_Window_ID
|
||||
*/
|
||||
private void getPrintFormats (int AD_Table_ID, int AD_Window_ID)
|
||||
{
|
||||
|
@ -134,6 +135,9 @@ public class WReport implements EventListener<Event> {
|
|||
showPopup(); // below button
|
||||
} // getPrintFormats
|
||||
|
||||
/**
|
||||
* Show popup menu for the list of print formats found.
|
||||
*/
|
||||
private void showPopup() {
|
||||
m_popup = new Menupopup();
|
||||
for(int i = 0; i < m_list.size(); i++)
|
||||
|
@ -150,7 +154,7 @@ public class WReport implements EventListener<Event> {
|
|||
|
||||
/**
|
||||
* Launch Report
|
||||
* @param pp Key=AD_PrintFormat_ID
|
||||
* @param pp KeyNamePair(AD_PrintFormat_ID,Name)
|
||||
*/
|
||||
private void launchReport (KeyNamePair pp)
|
||||
{
|
||||
|
@ -202,7 +206,7 @@ public class WReport implements EventListener<Event> {
|
|||
}
|
||||
} // launchReport
|
||||
|
||||
/**************************************************************************
|
||||
/**
|
||||
* Get AD_Table_ID for Table Name
|
||||
* @param tableName table name
|
||||
* @return AD_Table_ID or 0
|
||||
|
@ -212,9 +216,11 @@ public class WReport implements EventListener<Event> {
|
|||
return MTable.getTable_ID(tableName);
|
||||
} // getAD_Table_ID
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
if(event.getTarget() instanceof Menuitem)
|
||||
{
|
||||
//ON_CLICK event from showPopup() menu item.
|
||||
Menuitem mi = (Menuitem) event.getTarget();
|
||||
launchReport(m_list.get(Integer.parseInt(mi.getValue().toString())));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue