IDEMPIERE-5772 - Quick Info Widget Support for Info Window (#1899)

* IDEMPIERE-5772 - Quick Info Widget Support for Info Window - initial commit

* IDEMPIERE-5772 - manage context variables in info window

Put the following values into the context:
- query criteria
- values of the selected row

* IDEMPIERE-5772 - fixes

- info window should not change context if isLookup() = true (popup window mode)
- parameter values should be put into context only on re-query
- values of KeyNamePair type should use the "key" in context (practically tat means the ID) instead of name (display value)

* IDEMPIERE-5772 - add prefix to row variables and Selected_ID to ctx

* IDEMPIERE-5772 - rename variable name Selected_ID -> ID_Selection

* IDEMPIERE-5772 - patch by Carlos

* IDEMPIERE-5772 - fixed reported issues

- support ctx variables in info windows without process (no multiselection)
- change ctx variable syntax/prefix
- fix issue with type IDColumn
This commit is contained in:
Peter Takács 2023-07-16 17:33:58 +02:00 committed by GitHub
parent 407b756cb8
commit ca98a81671
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 404 additions and 27 deletions

View File

@ -0,0 +1,53 @@
-- IDEMPIERE-5772
SELECT register_migration_script('202306190914_IDEMPIERE-5772.sql') FROM dual;
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Jun 19, 2023, 9:14:41 AM CEST
INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,Help,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215853,0,'Info Window','Info and search/select Window','The Info window is used to search and select records as well as display information relevant to the selection.',200108,'AD_InfoWindow_ID',22,'N','N','N','N','N',0,'N',19,0,0,'Y',TO_TIMESTAMP('2023-06-19 09:14:40','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-06-19 09:14:40','YYYY-MM-DD HH24:MI:SS'),100,3068,'Y','N','D','N','N','N','Y','78d7ed91-8563-461a-ab16-39e62c393e78','Y',0,'N','N','C','N')
;
-- Jun 19, 2023, 9:14:44 AM CEST
UPDATE AD_Column SET FKConstraintName='ADInfoWindow_ADStatusLineUsedI', FKConstraintType='C',Updated=TO_TIMESTAMP('2023-06-19 09:14:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215853
;
-- Jun 19, 2023, 9:14:44 AM CEST
ALTER TABLE AD_StatusLineUsedIn ADD AD_InfoWindow_ID NUMBER(10) DEFAULT NULL
;
-- Jun 19, 2023, 9:14:44 AM CEST
ALTER TABLE AD_StatusLineUsedIn ADD CONSTRAINT ADInfoWindow_ADStatusLineUsedI FOREIGN KEY (AD_InfoWindow_ID) REFERENCES ad_infowindow(ad_infowindow_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
;
-- Jun 19, 2023, 9:15:04 AM CEST
INSERT INTO AD_Field (AD_Field_ID,Name,Description,Help,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207654,'Info Window','Info and search/select Window','The Info window is used to search and select records as well as display information relevant to the selection.',200115,215853,'Y',22,110,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-06-19 09:15:03','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-06-19 09:15:03','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','2ab90c17-a77d-4b89-bc17-17dc3f7b775d','Y',80,2)
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Window_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=40,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202573
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Table_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=60,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202574
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Table_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=70,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202575
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET IsDisplayed='Y', DisplayLogic='@AD_Table_ID@=0 & @AD_Window_ID@=0', SeqNo=80, XPosition=1,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207654
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET SeqNo=100,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202576
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202578
;
-- Jul 13, 2023, 6:38:30 PM CEST
UPDATE AD_Column SET DefaultValue='NULL',Updated=TO_TIMESTAMP('2023-07-13 18:38:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215853
;

View File

@ -0,0 +1,50 @@
-- IDEMPIERE-5772
SELECT register_migration_script('202306190914_IDEMPIERE-5772.sql') FROM dual;
-- Jun 19, 2023, 9:14:41 AM CEST
INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,Help,AD_Table_ID,ColumnName,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure,FKConstraintType,IsHtml) VALUES (215853,0,'Info Window','Info and search/select Window','The Info window is used to search and select records as well as display information relevant to the selection.',200108,'AD_InfoWindow_ID',22,'N','N','N','N','N',0,'N',19,0,0,'Y',TO_TIMESTAMP('2023-06-19 09:14:40','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-06-19 09:14:40','YYYY-MM-DD HH24:MI:SS'),100,3068,'Y','N','D','N','N','N','Y','78d7ed91-8563-461a-ab16-39e62c393e78','Y',0,'N','N','C','N')
;
-- Jun 19, 2023, 9:14:44 AM CEST
UPDATE AD_Column SET FKConstraintName='ADInfoWindow_ADStatusLineUsedI', FKConstraintType='C',Updated=TO_TIMESTAMP('2023-06-19 09:14:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215853
;
-- Jun 19, 2023, 9:14:44 AM CEST
ALTER TABLE AD_StatusLineUsedIn ADD COLUMN AD_InfoWindow_ID NUMERIC(10) DEFAULT NULL
;
-- Jun 19, 2023, 9:14:44 AM CEST
ALTER TABLE AD_StatusLineUsedIn ADD CONSTRAINT ADInfoWindow_ADStatusLineUsedI FOREIGN KEY (AD_InfoWindow_ID) REFERENCES ad_infowindow(ad_infowindow_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
;
-- Jun 19, 2023, 9:15:04 AM CEST
INSERT INTO AD_Field (AD_Field_ID,Name,Description,Help,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,ColumnSpan) VALUES (207654,'Info Window','Info and search/select Window','The Info window is used to search and select records as well as display information relevant to the selection.',200115,215853,'Y',22,110,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2023-06-19 09:15:03','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-06-19 09:15:03','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','2ab90c17-a77d-4b89-bc17-17dc3f7b775d','Y',80,2)
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Window_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=40,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202573
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Table_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=60,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202574
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET DisplayLogic='@AD_Table_ID@=0 & @AD_InfoWindow_ID@=0', SeqNo=70,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202575
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET IsDisplayed='Y', DisplayLogic='@AD_Table_ID@=0 & @AD_Window_ID@=0', SeqNo=80, XPosition=1,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=207654
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET SeqNo=100,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202576
;
-- Jun 19, 2023, 9:22:16 AM CEST
UPDATE AD_Field SET SeqNo=110,Updated=TO_TIMESTAMP('2023-06-19 09:22:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202578
;
-- Jul 13, 2023, 6:38:30 PM CEST
UPDATE AD_Column SET DefaultValue='NULL',Updated=TO_TIMESTAMP('2023-07-13 18:38:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=215853
;

View File

@ -49,6 +49,21 @@ public interface I_AD_StatusLineUsedIn
*/ */
public int getAD_Client_ID(); public int getAD_Client_ID();
/** Column name AD_InfoWindow_ID */
public static final String COLUMNNAME_AD_InfoWindow_ID = "AD_InfoWindow_ID";
/** Set Info Window.
* Info and search/select Window
*/
public void setAD_InfoWindow_ID (int AD_InfoWindow_ID);
/** Get Info Window.
* Info and search/select Window
*/
public int getAD_InfoWindow_ID();
public org.compiere.model.I_AD_InfoWindow getAD_InfoWindow() throws RuntimeException;
/** Column name AD_Org_ID */ /** Column name AD_Org_ID */
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID"; public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";

View File

@ -189,7 +189,19 @@ public class MStatusLine extends X_AD_StatusLine implements ImmutablePOSupport
* @return array of widget lines discovered for table or specific tab or general window * @return array of widget lines discovered for table or specific tab or general window
*/ */
public static MStatusLine[] getStatusLinesWidget(int window_ID, int tab_ID, int table_ID) { public static MStatusLine[] getStatusLinesWidget(int window_ID, int tab_ID, int table_ID) {
StringBuilder key = new StringBuilder().append(window_ID).append("|").append(tab_ID).append("|").append(table_ID); return getStatusLinesWidget(window_ID, tab_ID, table_ID, 0);
}
/**
* Get the widget lines defined for the window and tab and table (immutable)
* @param window_ID
* @param tab_ID
* @param table_ID
* @param infoWindow_ID
* @return array of widget lines discovered for table or specific tab or general window
*/
public static MStatusLine[] getStatusLinesWidget(int window_ID, int tab_ID, int table_ID, int infoWindow_ID) {
StringBuilder key = new StringBuilder().append(window_ID).append("|").append(tab_ID).append("|").append(table_ID).append("|").append(infoWindow_ID);
MStatusLine[] retValue = null; MStatusLine[] retValue = null;
if (s_cachew.containsKey(key.toString())) if (s_cachew.containsKey(key.toString()))
{ {
@ -205,9 +217,12 @@ public class MStatusLine extends X_AD_StatusLine implements ImmutablePOSupport
+ "WHERE slu.IsActive = 'Y' " + "WHERE slu.IsActive = 'Y' "
+ " AND sl.IsActive = 'Y' " + " AND sl.IsActive = 'Y' "
+ " AND slu.IsStatusLine = 'N' " + " AND slu.IsStatusLine = 'N' "
+ " AND (slu.AD_Table_ID = ? OR (slu.AD_Window_ID=? AND slu.AD_Tab_ID=?) OR (slu.AD_Window_ID=? AND slu.AD_Tab_ID IS NULL)) " + " AND (slu.AD_Table_ID = ? "
+ " OR (slu.AD_Window_ID=? AND slu.AD_Tab_ID=?) "
+ " OR (slu.AD_Window_ID=? AND slu.AD_Tab_ID IS NULL)"
+ " OR slu.AD_InfoWindow_ID=?) "
+ "ORDER BY slu.SeqNo"; + "ORDER BY slu.SeqNo";
int[] wlids = DB.getIDsEx(null, sql, table_ID, window_ID, tab_ID, window_ID); int[] wlids = DB.getIDsEx(null, sql, table_ID, window_ID, tab_ID, window_ID, infoWindow_ID);
if (wlids.length > 0) { if (wlids.length > 0) {
ArrayList<MStatusLine> list = new ArrayList<MStatusLine>(); ArrayList<MStatusLine> list = new ArrayList<MStatusLine>();
for (int wlid : wlids) { for (int wlid : wlids) {

View File

@ -71,11 +71,21 @@ public class MStatusLineUsedIn extends X_AD_StatusLineUsedIn
if (getAD_Table_ID() > 0) { if (getAD_Table_ID() > 0) {
setAD_Window_ID(0); setAD_Window_ID(0);
setAD_Tab_ID(0); setAD_Tab_ID(0);
} else { setAD_InfoWindow_ID(0);
if (getAD_Window_ID() <= 0) { }
log.saveError("SaveError", Msg.parseTranslation(getCtx(), "@FillMandatory@ @AD_Table_ID@ @AD_Window_ID@")); else if (getAD_Window_ID() > 0) {
return false; setAD_Table_ID(0);
} setAD_InfoWindow_ID(0);
}
else if (getAD_InfoWindow_ID() > 0) {
setAD_Table_ID(0);
setAD_Window_ID(0);
setAD_Tab_ID(0);
}
else {
log.saveError("SaveError", Msg.parseTranslation(getCtx(), "@FillMandatory@ @AD_Table_ID@ @AD_Window_ID@ @AD_InfoWindow_ID@"));
return false;
} }
return true; return true;
} }

View File

@ -30,7 +30,7 @@ public class X_AD_StatusLineUsedIn extends PO implements I_AD_StatusLineUsedIn,
/** /**
* *
*/ */
private static final long serialVersionUID = 20230409L; private static final long serialVersionUID = 20230619L;
/** Standard Constructor */ /** Standard Constructor */
public X_AD_StatusLineUsedIn (Properties ctx, int AD_StatusLineUsedIn_ID, String trxName) public X_AD_StatusLineUsedIn (Properties ctx, int AD_StatusLineUsedIn_ID, String trxName)
@ -147,6 +147,34 @@ public class X_AD_StatusLineUsedIn extends PO implements I_AD_StatusLineUsedIn,
return ii.intValue(); return ii.intValue();
} }
public org.compiere.model.I_AD_InfoWindow getAD_InfoWindow() throws RuntimeException
{
return (org.compiere.model.I_AD_InfoWindow)MTable.get(getCtx(), org.compiere.model.I_AD_InfoWindow.Table_ID)
.getPO(getAD_InfoWindow_ID(), get_TrxName());
}
/** Set Info Window.
@param AD_InfoWindow_ID Info and search/select Window
*/
public void setAD_InfoWindow_ID (int AD_InfoWindow_ID)
{
if (AD_InfoWindow_ID < 1)
set_Value (COLUMNNAME_AD_InfoWindow_ID, null);
else
set_Value (COLUMNNAME_AD_InfoWindow_ID, Integer.valueOf(AD_InfoWindow_ID));
}
/** Get Info Window.
@return Info and search/select Window
*/
public int getAD_InfoWindow_ID()
{
Integer ii = (Integer)get_Value(COLUMNNAME_AD_InfoWindow_ID);
if (ii == null)
return 0;
return ii.intValue();
}
/** Set AD_StatusLineUsedIn. /** Set AD_StatusLineUsedIn.
@param AD_StatusLineUsedIn_ID AD_StatusLineUsedIn @param AD_StatusLineUsedIn_ID AD_StatusLineUsedIn
*/ */

View File

@ -49,6 +49,7 @@ import org.adempiere.webui.panel.ADForm;
import org.adempiere.webui.panel.BroadcastMessageWindow; import org.adempiere.webui.panel.BroadcastMessageWindow;
import org.adempiere.webui.panel.HeaderPanel; import org.adempiere.webui.panel.HeaderPanel;
import org.adempiere.webui.panel.HelpController; import org.adempiere.webui.panel.HelpController;
import org.adempiere.webui.panel.InfoPanel;
import org.adempiere.webui.panel.TimeoutPanel; import org.adempiere.webui.panel.TimeoutPanel;
import org.adempiere.webui.part.ITabOnSelectHandler; import org.adempiere.webui.part.ITabOnSelectHandler;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
@ -1034,6 +1035,11 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
@Override @Override
public void updateHelpContext(String ctxType, int recordId) { public void updateHelpContext(String ctxType, int recordId) {
this.updateHelpContext(ctxType, recordId, null);
}
@Override
public void updateHelpContext(String ctxType, int recordId, InfoPanel infoPanel) {
// don't show context for SetupWizard Form, is managed internally using wf and node ctxhelp // don't show context for SetupWizard Form, is managed internally using wf and node ctxhelp
if (recordId == SystemIDs.FORM_SETUP_WIZARD && X_AD_CtxHelp.CTXTYPE_Form.equals(ctxType)) if (recordId == SystemIDs.FORM_SETUP_WIZARD && X_AD_CtxHelp.CTXTYPE_Form.equals(ctxType))
return; return;
@ -1047,7 +1053,10 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
if (adwindow != null) { if (adwindow != null) {
gridTab = adwindow.getADWindowContent().getActiveGridTab(); gridTab = adwindow.getADWindowContent().getActiveGridTab();
} }
updateHelpQuickInfo(gridTab); if(X_AD_CtxHelp.CTXTYPE_Info.equals(ctxType))
updateHelpQuickInfo(infoPanel);
else
updateHelpQuickInfo(gridTab);
} }
@Override @Override
@ -1060,6 +1069,12 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
helpController.renderToolTip(hdr, desc, help, otherContent); helpController.renderToolTip(hdr, desc, help, otherContent);
} }
@Override
public void updateHelpQuickInfo(InfoPanel infoPanel) {
if (isQuickInfoOpen)
helpController.renderQuickInfo(infoPanel);
}
@Override @Override
public void updateHelpQuickInfo(GridTab gridTab) { public void updateHelpQuickInfo(GridTab gridTab) {
this.gridTab = gridTab; this.gridTab = gridTab;
@ -1084,7 +1099,8 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
@Override @Override
public void openInfo(int infoId) { public void openInfo(int infoId) {
super.openInfo(infoId); super.openInfo(infoId);
updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoId); // updateHelpContext is already called in InfoPanel onPageAttached method - IDEMPIERE-5772
// updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoId);
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.apps.ProcessDialog; import org.adempiere.webui.apps.ProcessDialog;
import org.adempiere.webui.component.Window; import org.adempiere.webui.component.Window;
import org.adempiere.webui.panel.ADForm; import org.adempiere.webui.panel.ADForm;
import org.adempiere.webui.panel.InfoPanel;
import org.adempiere.webui.part.UIPart; import org.adempiere.webui.part.UIPart;
import org.compiere.model.GridField; import org.compiere.model.GridField;
import org.compiere.model.GridTab; import org.compiere.model.GridTab;
@ -220,6 +221,13 @@ public interface IDesktop extends UIPart {
} }
} }
/**
* update help content in help/info panel
* @param infoWindowId
* @param infoPanel
*/
public void updateHelpContext(String ctxType, int infoWindowId, InfoPanel infoPanel);
/** /**
* update help content in help/info panel * update help content in help/info panel
* @param ctxTypes * @param ctxTypes
@ -248,6 +256,12 @@ public interface IDesktop extends UIPart {
*/ */
public void updateHelpQuickInfo(GridTab gridTab); public void updateHelpQuickInfo(GridTab gridTab);
/**
* update quick info (status line) in help/info panel
* @param infoPanel
*/
public void updateHelpQuickInfo(InfoPanel infoPanel);
/** /**
* *
* @return true if there are changes not save yet * @return true if there are changes not save yet

View File

@ -480,7 +480,7 @@ public abstract class WEditor implements EventListener<Event>, PropertyChangeLis
* Fire ValueChangeEvent to ValueChangeListener in {@link #listeners} * Fire ValueChangeEvent to ValueChangeListener in {@link #listeners}
* @param event * @param event
*/ */
protected void fireValueChange(ValueChangeEvent event) public void fireValueChange(ValueChangeEvent event)
{ {
//copy to array to avoid concurrent modification exception //copy to array to avoid concurrent modification exception
ValueChangeListener[] vcl = new ValueChangeListener[listeners.size()]; ValueChangeListener[] vcl = new ValueChangeListener[listeners.size()];

View File

@ -1904,10 +1904,12 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
mField.addPropertyChangeListener(editor); mField.addPropertyChangeListener(editor);
mField.setValue(mField.getDefaultForPanel(), true); mField.setValue(mField.getDefaultForPanel(), true);
editor.fireValueChange(new ValueChangeEvent(editor, mField.getColumnName(), mField.getOldValue(), mField.getValue()));
if(infoColumn.isRange()) { if(infoColumn.isRange()) {
mField2.addPropertyChangeListener(editor2); mField2.addPropertyChangeListener(editor2);
mField2.setValue(mField2.getDefaultForPanel(), true); mField2.setValue(mField2.getDefaultForPanel(), true);
editor2.fireValueChange(new ValueChangeEvent(editor2, mField2.getColumnName(), mField2.getOldValue(), mField2.getValue()));
} }
} // addSelectionColumn } // addSelectionColumn
@ -2199,15 +2201,19 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
if (evt.getNewValue() == null) { if (evt.getNewValue() == null) {
Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), ""); Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), "");
Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), ""); Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), "");
paraCtxValues.put(editor.getColumnName(), "");
} else if (evt.getNewValue() instanceof Boolean) { } else if (evt.getNewValue() instanceof Boolean) {
Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), (Boolean)evt.getNewValue()); Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), (Boolean)evt.getNewValue());
Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), (Boolean)evt.getNewValue()); Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), (Boolean)evt.getNewValue());
paraCtxValues.put(editor.getColumnName(), (Boolean)evt.getNewValue());
} else if (evt.getNewValue() instanceof Timestamp) { } else if (evt.getNewValue() instanceof Timestamp) {
Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), (Timestamp)evt.getNewValue()); Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), (Timestamp)evt.getNewValue());
Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO+"|"+editor.getColumnName(), (Timestamp)evt.getNewValue()); Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO+"|"+editor.getColumnName(), (Timestamp)evt.getNewValue());
paraCtxValues.put(editor.getColumnName(), (Timestamp)evt.getNewValue());
} else { } else {
Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), evt.getNewValue().toString()); Env.setContext(infoContext, p_WindowNo, editor.getColumnName(), evt.getNewValue().toString());
Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), evt.getNewValue().toString()); Env.setContext(infoContext, p_WindowNo, Env.TAB_INFO, editor.getColumnName(), evt.getNewValue().toString());
paraCtxValues.put(editor.getColumnName(), evt.getNewValue().toString());
} }
dynamicDisplay(editor); dynamicDisplay(editor);

View File

@ -662,11 +662,22 @@ public class HelpController
} }
} }
public void renderQuickInfo(GridTab gridTab) { public void renderQuickInfo(Object obj) {
if (gridTab == null) { if (obj == null) {
pnlQuickInfo.setVisible(false); pnlQuickInfo.setVisible(false);
} else { } else {
String widget = gridTab.getStatusLinesWidget(); String widget = "";
if(obj instanceof GridTab) {
widget = ((GridTab)obj).getStatusLinesWidget();
}
else if(obj instanceof InfoPanel) {
widget = ((InfoPanel)obj).getStatusLinesWidget();
}
else {
pnlQuickInfo.setVisible(false);
return;
}
if (widget == null) { if (widget == null) {
pnlQuickInfo.setVisible(false); pnlQuickInfo.setVisible(false);
} else { } else {

View File

@ -35,6 +35,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects;
import java.util.Vector; import java.util.Vector;
import java.util.logging.Level; import java.util.logging.Level;
@ -73,6 +74,7 @@ import org.adempiere.webui.window.Dialog;
import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.ColumnInfo;
import org.compiere.minigrid.IDColumn; import org.compiere.minigrid.IDColumn;
import org.compiere.minigrid.UUIDColumn; import org.compiere.minigrid.UUIDColumn;
import org.compiere.model.AccessSqlParser.TableInfo;
import org.compiere.model.GridField; import org.compiere.model.GridField;
import org.compiere.model.InfoColumnVO; import org.compiere.model.InfoColumnVO;
import org.compiere.model.InfoRelatedVO; import org.compiere.model.InfoRelatedVO;
@ -82,10 +84,10 @@ import org.compiere.model.MPInstance;
import org.compiere.model.MProcess; import org.compiere.model.MProcess;
import org.compiere.model.MRefTable; import org.compiere.model.MRefTable;
import org.compiere.model.MRole; import org.compiere.model.MRole;
import org.compiere.model.MStatusLine;
import org.compiere.model.MSysConfig; import org.compiere.model.MSysConfig;
import org.compiere.model.MTable; import org.compiere.model.MTable;
import org.compiere.model.X_AD_CtxHelp; import org.compiere.model.X_AD_CtxHelp;
import org.compiere.model.AccessSqlParser.TableInfo;
import org.compiere.process.ProcessInfo; import org.compiere.process.ProcessInfo;
import org.compiere.process.ProcessInfoLog; import org.compiere.process.ProcessInfoLog;
import org.compiere.process.ProcessInfoUtil; import org.compiere.process.ProcessInfoUtil;
@ -141,6 +143,8 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
protected static final String ON_USER_QUERY_ATTR = "ON_USER_QUERY"; protected static final String ON_USER_QUERY_ATTR = "ON_USER_QUERY";
protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError"; protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError";
protected static final String COLUMN_VISIBLE_ORIGINAL = "column.visible.original"; protected static final String COLUMN_VISIBLE_ORIGINAL = "column.visible.original";
protected static final String ROW_CTX_VARIABLE_PREFIX = "_IWInfo_";
protected static final String ROW_ID_CTX_VARIABLE_NAME = "_IWInfoIDs_Selected";
private final static int DEFAULT_PAGE_SIZE = 100; private final static int DEFAULT_PAGE_SIZE = 100;
private final static int DEFAULT_PAGE_PRELOAD = 4; private final static int DEFAULT_PAGE_PRELOAD = 4;
@ -614,6 +618,19 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
*/ */
private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx())); private boolean isUseEscForTabClosing = MSysConfig.getBooleanValue(MSysConfig.USE_ESC_FOR_TAB_CLOSING, false, Env.getAD_Client_ID(Env.getCtx()));
/**
* Contains the indexes of selected row, maintains the selection order
*/
protected ArrayList<Integer> m_rowSelectionOrder = new ArrayList<Integer>();
/**
* Number of selected rows
*/
protected int m_selectedCount = 0;
/**
* Values that will be put into the context on re-query
*/
protected HashMap<String, Object> paraCtxValues = new HashMap<String, Object>();
/** /**
* Loaded correctly * Loaded correctly
* @return true if loaded OK * @return true if loaded OK
@ -647,10 +664,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
*/ */
public void setStatusSelected () public void setStatusSelected ()
{ {
if (!p_multipleSelection) int selectedCount = p_multipleSelection ? recordSelectedData.size() : 0;
return;
int selectedCount = recordSelectedData.size();
for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){ for (int rowIndex = 0; rowIndex < contentPanel.getModel().getRowCount(); rowIndex++){
Object keyCandidate = getColumnValue(rowIndex); Object keyCandidate = getColumnValue(rowIndex);
@ -659,16 +673,20 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
List<Object> candidateRecord = (List<Object>)contentPanel.getModel().get(rowIndex); List<Object> candidateRecord = (List<Object>)contentPanel.getModel().get(rowIndex);
if (contentPanel.getModel().isSelected(candidateRecord)){ if (contentPanel.getModel().isSelected(candidateRecord)){
if (!recordSelectedData.containsKey(keyCandidate)){ if(!p_multipleSelection) {
selectedCount++;
break;
}
else if (!recordSelectedData.containsKey(keyCandidate)){
selectedCount++; selectedCount++;
} }
}else{ }else if (p_multipleSelection){
if (recordSelectedData.containsKey(keyCandidate)){// unselected record if (recordSelectedData.containsKey(keyCandidate)){// unselected record
selectedCount--; selectedCount--;
} }
} }
} }
m_selectedCount = selectedCount;
String msg = Msg.getMsg(Env.getCtx(), "IWStatusSelected", new Object [] {String.valueOf(selectedCount)}); String msg = Msg.getMsg(Env.getCtx(), "IWStatusSelected", new Object [] {String.valueOf(selectedCount)});
statusBar.setSelectedRowNumber(msg); statusBar.setSelectedRowNumber(msg);
btnSelectAll.setEnabled(m_count > 0 && selectedCount != m_count); btnSelectAll.setEnabled(m_count > 0 && selectedCount != m_count);
@ -2218,6 +2236,10 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
} }
enableButtons(); enableButtons();
if(!isLookup()) {
updateRowSelectionOrder();
updateContext(false);
}
}else if (event.getTarget() == contentPanel && event.getName().equals("onAfterRender")){ }else if (event.getTarget() == contentPanel && event.getName().equals("onAfterRender")){
//IDEMPIERE-1334 at this event selected item from listBox and model is sync //IDEMPIERE-1334 at this event selected item from listBox and model is sync
@ -2260,6 +2282,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_REFRESH))) else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_REFRESH)))
{ {
recordSelectedData.clear(); recordSelectedData.clear();
setStatusSelected();
onUserQuery(); onUserQuery();
} }
else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CANCEL))) else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CANCEL)))
@ -2307,10 +2330,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
else if (ON_SELECT_ALL_RECORDS.equals(event.getName())) else if (ON_SELECT_ALL_RECORDS.equals(event.getName()))
{ {
selectAllRecords(); selectAllRecords();
if(!isLookup()) {
updateRowSelectionOrder();
updateContext(false);
}
} }
else if (event.getTarget().equals(btnDeSelectAll)) else if (event.getTarget().equals(btnDeSelectAll))
{ {
deSelectAllRecords(); deSelectAllRecords();
if(!isLookup()) {
updateRowSelectionOrder();
updateContext(false);
}
} }
// IDEMPIERE-1334 handle event click into process button start // IDEMPIERE-1334 handle event click into process button start
else if (ON_RUN_PROCESS.equals(event.getName())){ else if (ON_RUN_PROCESS.equals(event.getName())){
@ -2380,7 +2411,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT))
{ {
if (infoWindow != null) if (infoWindow != null)
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID()); SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID(), this);
else else
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0); SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0);
} }
@ -2859,6 +2890,10 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
isQueryByUser = false; isQueryByUser = false;
hideBusyDialog(); hideBusyDialog();
} }
if(!isLookup()) {
updateRowSelectionOrder();
updateContext(true);
}
} }
/** /**
@ -3222,11 +3257,11 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
@Override @Override
public void onPageAttached(Page newpage, Page oldpage) { public void onPageAttached(Page newpage, Page oldpage) {
super.onPageAttached(newpage, oldpage); super.onPageAttached(newpage, oldpage);
if (newpage != null) { if (newpage != null && !isLookup()) {
if (infoWindow != null) if (infoWindow != null)
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID()); SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID(), this);
else else
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0); SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0, this);
} }
SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this); SessionManager.getSessionApplication().getKeylistener().addEventListener(Events.ON_CTRL_KEY, this);
} }
@ -3300,4 +3335,128 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
btnDeSelectAll.setVisible(multipleSelection); btnDeSelectAll.setVisible(multipleSelection);
} }
/**
* Widget support
* Depending on Window/Tab returns widget lines info
* @return info
*/
public String getStatusLinesWidget() {
if(infoWindow == null)
return null;
MStatusLine[] wls = MStatusLine.getStatusLinesWidget(0, 0, 0, infoWindow.getAD_InfoWindow_ID());
if (wls != null && wls.length > 0)
{
StringBuilder lines = new StringBuilder();
for (MStatusLine wl : wls) {
String line = wl.parseLine(getWindowNo());
if (line != null) {
lines.append(line).append("<br>");
}
}
if (lines.length() > 0)
return lines.toString();
}
return null;
} // getWidgetLines
/**
* Update row selection order
*/
protected void updateRowSelectionOrder() {
if(m_selectedCount == m_count) {
for(int rowIdx = 0; rowIdx < m_count; rowIdx++) {
if(!m_rowSelectionOrder.contains(rowIdx))
m_rowSelectionOrder.add((Integer)rowIdx);
}
}
else if(m_selectedCount == 0) {
m_rowSelectionOrder.clear();
}
else {
if(!p_multipleSelection) {
m_rowSelectionOrder.clear();
m_rowSelectionOrder.add(m_lastSelectedIndex);
}
else {
if(m_rowSelectionOrder.contains(m_lastSelectedIndex))
m_rowSelectionOrder.remove((Integer)m_lastSelectedIndex);
else
m_rowSelectionOrder.add(m_lastSelectedIndex);
}
}
} // updateRowSelectionOrder
/**
* Put values from the selected row into the context
*/
protected void updateContext(boolean checkQueryCriteria) {
Map<Object, List<Object>> rowInfo = getSelectedRowInfo();
List<Object> lastSelectedRow = m_rowSelectionOrder.size() > 0 ? rowInfo.get(getRowKeyAt(m_rowSelectionOrder.get(m_rowSelectionOrder.size() - 1))) : null;
if(checkQueryCriteria) {
// put parameter values into the context
for(Map.Entry<String, Object> e : paraCtxValues.entrySet()) {
String columnName = e.getKey();
Object value = e.getValue();
setContext(columnName, value);
}
}
// put the values of the last selected row into the context
for(int i = 0; i < p_layout.length; i++) {
String columnName = p_layout[i].getColumnName();
Object value = lastSelectedRow != null ? lastSelectedRow.get(i) : null;
setContext(ROW_CTX_VARIABLE_PREFIX + columnName, value);
}
// add selected IDs to the context
setContext(ROW_ID_CTX_VARIABLE_NAME, getSelectedIDsForCtx());
// update Quick Info widget
if (infoWindow != null)
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID(), this);
else
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0, this);
} // updateContext
/**
* Set context
* @param columnName
* @param value
*/
protected void setContext(String columnName, Object value) {
if(value instanceof KeyNamePair)
value = ((KeyNamePair)value).getKey();
else if(value instanceof IDColumn)
value = ((IDColumn)value).getRecord_ID();
if (value == null) {
Env.setContext(Env.getCtx(), p_WindowNo, columnName, "");
} else if (value instanceof Boolean) {
Env.setContext(Env.getCtx(), p_WindowNo, columnName, (Boolean)value);
} else if (value instanceof Timestamp) {
Env.setContext(Env.getCtx(), p_WindowNo, columnName, (Timestamp)value);
} else {
Env.setContext(Env.getCtx(), p_WindowNo, columnName, value.toString());
}
}
/**
* Get a comma-separated string of selected IDs
* @return String ctx value
*/
protected String getSelectedIDsForCtx() {
String returnVal = null;
for(int idx : m_rowSelectionOrder) {
String selectedID = Objects.toString(getRowKeyAt(idx));
if(returnVal == null)
returnVal = selectedID;
else
returnVal += "," + selectedID;
}
return returnVal;
}
} // Info } // Info