IDEMPIERE-3413 Multi Select List and table reference
This commit is contained in:
parent
cc8f48acd2
commit
d00c07c2b9
|
@ -0,0 +1,86 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Dec 4, 2018 3:41:36 PM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200161,'Chosen Multiple Selection List','fa2c2787-e93f-42be-a5d1-7a12f6b30b72','N','Chosen multiple selection box for reference list','D',TO_DATE('2018-12-04 15:41:35','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2018-12-04 15:41:35','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:41:56 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200162,'Chosen Multiple Selection Table','07d7bf33-8998-4538-920d-5c0e0b2d46d2','N','Chosen multiple selection box for table list','D',TO_DATE('2018-12-04 15:41:56','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2018-12-04 15:41:56','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:44:27 PM MYT
|
||||
UPDATE AD_Val_Rule SET Code='AD_Reference.ValidationType=CASE WHEN @AD_Reference_ID@ IN (17,28,200152,200161) THEN ''L'' ELSE ''T'' END',Updated=TO_DATE('2018-12-04 15:44:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Val_Rule_ID=115
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:48:07 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200152 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-04 15:48:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:48:49 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=19 | @AD_Reference_ID@=28 | @AD_Reference_ID@=30 | @AD_Reference_ID@=200012 | @AD_Reference_ID@=31 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-04 15:48:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=172
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:49:17 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200163,'Chosen Multiple Selection Search','563a482c-4f06-448d-bb7f-e109d33cead9','N','Chosen multiple selection box for search','D',TO_DATE('2018-12-04 16:49:16','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2018-12-04 16:49:16','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:49:55 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=19 | @AD_Reference_ID@=28 | @AD_Reference_ID@=30 | @AD_Reference_ID@=200012 | @AD_Reference_ID@=31 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-04 16:49:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=172
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:50:41 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200152 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-04 16:50:41','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 5, 2018 11:18:30 AM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
UPDATE AD_Field SET AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-05 11:18:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 7, 2018 4:37:39 PM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
UPDATE AD_Field SET AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2018-12-07 16:37:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=2540
|
||||
;
|
||||
|
||||
-- IDEMPIERE-3413 Multi Select List and table reference
|
||||
-- Jun 22, 2019, 5:11:30 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2019-06-22 17:11:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201622
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:12:43 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsQueryCriteria@=Y & @AD_Reference_ID@!200161 & @AD_Reference_ID@!200162 & @AD_Reference_ID@!200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2019-06-22 17:12:43','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201636
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:13:24 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsQueryCriteria@=Y & @AD_Reference_ID@!200161 & @AD_Reference_ID@!200162 & @AD_Reference_ID@!200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2019-06-22 17:13:24','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201635
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:15:39 PM MYT
|
||||
UPDATE AD_Field SET AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', IsToolbarButton=NULL,Updated=TO_DATE('2019-06-22 17:15:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201622
|
||||
;
|
||||
|
||||
CREATE TYPE TABLE_OF_VARCHAR2 AS TABLE OF VARCHAR2(4000)
|
||||
;
|
||||
|
||||
CREATE OR REPLACE FUNCTION toTableOfVarchar2(p_list IN VARCHAR2)
|
||||
RETURN TABLE_OF_VARCHAR2 DETERMINISTIC
|
||||
AS
|
||||
l_tab TABLE_OF_VARCHAR2 := TABLE_OF_VARCHAR2();
|
||||
BEGIN
|
||||
FOR i IN
|
||||
( select trim('"' from REGEXP_SUBSTR(p_list, '(".*?"|.*?)(,|$)', 1, level, NULL, 1)) split
|
||||
from dual
|
||||
connect by level<=length(regexp_replace(p_list,'".*?"|[^,]*'))+1)
|
||||
LOOP
|
||||
l_tab.EXTEND;
|
||||
l_tab(l_tab.COUNT) := i.split;
|
||||
END LOOP;
|
||||
RETURN l_tab;
|
||||
END toTableOfVarchar2
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201906171811_IDEMPIERE-3413.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
-- Dec 4, 2018 3:41:36 PM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200161,'Chosen Multiple Selection List','fa2c2787-e93f-42be-a5d1-7a12f6b30b72','N','Chosen multiple selection box for reference list','D',TO_TIMESTAMP('2018-12-04 15:41:35','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2018-12-04 15:41:35','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:41:56 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200162,'Chosen Multiple Selection Table','07d7bf33-8998-4538-920d-5c0e0b2d46d2','N','Chosen multiple selection box for table list','D',TO_TIMESTAMP('2018-12-04 15:41:56','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2018-12-04 15:41:56','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:44:27 PM MYT
|
||||
UPDATE AD_Val_Rule SET Code='AD_Reference.ValidationType=CASE WHEN @AD_Reference_ID@ IN (17,28,200152,200161) THEN ''L'' ELSE ''T'' END',Updated=TO_TIMESTAMP('2018-12-04 15:44:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Val_Rule_ID=115
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:48:07 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200152 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-04 15:48:07','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 3:48:49 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=19 | @AD_Reference_ID@=28 | @AD_Reference_ID@=30 | @AD_Reference_ID@=200012 | @AD_Reference_ID@=31 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-04 15:48:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=172
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:49:17 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,Description,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200163,'Chosen Multiple Selection Search','563a482c-4f06-448d-bb7f-e109d33cead9','N','Chosen multiple selection box for search','D',TO_TIMESTAMP('2018-12-04 16:49:16','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2018-12-04 16:49:16','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:49:55 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=19 | @AD_Reference_ID@=28 | @AD_Reference_ID@=30 | @AD_Reference_ID@=200012 | @AD_Reference_ID@=31 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-04 16:49:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=172
|
||||
;
|
||||
|
||||
-- Dec 4, 2018 4:50:41 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200152 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-04 16:50:41','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 5, 2018 11:18:30 AM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
UPDATE AD_Field SET AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-05 11:18:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=171
|
||||
;
|
||||
|
||||
-- Dec 7, 2018 4:37:39 PM MYT
|
||||
-- AP2-766 Implement Chosen Box control
|
||||
UPDATE AD_Field SET AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2018-12-07 16:37:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=2540
|
||||
;
|
||||
|
||||
-- IDEMPIERE-3413 Multi Select List and table reference
|
||||
-- Jun 22, 2019, 5:11:30 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@AD_Reference_ID@=17 | @AD_Reference_ID@=18 | @AD_Reference_ID@=30 | @AD_Reference_ID@=28 | @AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-06-22 17:11:30','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201622
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:12:43 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsQueryCriteria@=Y & @AD_Reference_ID@!200161 & @AD_Reference_ID@!200162 & @AD_Reference_ID@!200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-06-22 17:12:43','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201636
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:13:24 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsQueryCriteria@=Y & @AD_Reference_ID@!200161 & @AD_Reference_ID@!200162 & @AD_Reference_ID@!200163', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-06-22 17:13:24','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201635
|
||||
;
|
||||
|
||||
-- Jun 22, 2019, 5:15:39 PM MYT
|
||||
UPDATE AD_Field SET AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, MandatoryLogic='@AD_Reference_ID@=200161 | @AD_Reference_ID@=200162 | @AD_Reference_ID@=200163', IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2019-06-22 17:15:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=201622
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201906171811_IDEMPIERE-3413.sql') FROM dual
|
||||
;
|
||||
|
|
@ -339,5 +339,18 @@ public interface AdempiereDatabase
|
|||
|
||||
public String getNameOfUniqueConstraintError(Exception e);
|
||||
|
||||
/**
|
||||
* @param columnName
|
||||
* @param csv comma separated value
|
||||
* @return subset sql clause
|
||||
*/
|
||||
public String subsetClauseForCSV(String columnName, String csv);
|
||||
|
||||
/**
|
||||
* @param columnName
|
||||
* @param csv comma separated value
|
||||
* @return subset sql clause
|
||||
*/
|
||||
public String intersectClauseForCSV(String columnName, String csv);
|
||||
} // AdempiereDatabase
|
||||
|
||||
|
|
|
@ -240,6 +240,27 @@ public final class MLookup extends Lookup implements Serializable
|
|||
if (key == null)
|
||||
return "";
|
||||
//
|
||||
if (m_info.DisplayType==DisplayType.ChosenMultipleSelectionList || m_info.DisplayType==DisplayType.ChosenMultipleSelectionSearch
|
||||
|| m_info.DisplayType==DisplayType.ChosenMultipleSelectionTable)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String[] keys = key.toString().split("[,]");
|
||||
for(String k : keys)
|
||||
{
|
||||
if (builder.length() > 0)
|
||||
builder.append(", ");
|
||||
Object display = get(k);
|
||||
if (display == null)
|
||||
{
|
||||
builder.append("<").append(k).append(">");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append(display.toString());
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
Object display = get (key);
|
||||
if (display == null){
|
||||
StringBuilder msgreturn = new StringBuilder("<").append(key.toString()).append(">");
|
||||
|
|
|
@ -185,13 +185,14 @@ public class MLookupFactory
|
|||
MLookupInfo info = null;
|
||||
boolean needToAddSecurity = true;
|
||||
// List
|
||||
if (AD_Reference_ID == DisplayType.List) // 17
|
||||
if (AD_Reference_ID == DisplayType.List || AD_Reference_ID == DisplayType.ChosenMultipleSelectionList) // 17
|
||||
{
|
||||
info = getLookup_List(language, AD_Reference_Value_ID);
|
||||
needToAddSecurity = false;
|
||||
}
|
||||
// Table or Search with Reference_Value
|
||||
else if ((AD_Reference_ID == DisplayType.Table || AD_Reference_ID == DisplayType.Search)
|
||||
else if ((AD_Reference_ID == DisplayType.Table || AD_Reference_ID == DisplayType.Search
|
||||
|| AD_Reference_ID == DisplayType.ChosenMultipleSelectionTable || AD_Reference_ID == DisplayType.ChosenMultipleSelectionSearch)
|
||||
&& AD_Reference_Value_ID != 0)
|
||||
{
|
||||
info = getLookup_Table (ctx, language, WindowNo, AD_Reference_Value_ID);
|
||||
|
|
|
@ -165,6 +165,25 @@ public class MQuery implements Serializable
|
|||
if (P_String != null)
|
||||
{
|
||||
if (P_String_To == null)
|
||||
{
|
||||
if (Reference_ID == DisplayType.ChosenMultipleSelectionList)
|
||||
{
|
||||
String columnName = TableName + "." + ParameterName;
|
||||
int cnt = DB.getSQLValueEx(null, "SELECT Count(*) From AD_Column WHERE IsActive='Y' AND AD_Client_ID=0 AND Upper(ColumnName)=? AND AD_Reference_ID=?", ParameterName.toUpperCase(), DisplayType.ChosenMultipleSelectionList);
|
||||
if (cnt > 0)
|
||||
query.addRestriction(DB.intersectClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info);
|
||||
else
|
||||
query.addRestriction(DB.inClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info);
|
||||
}
|
||||
else if (Reference_ID == DisplayType.ChosenMultipleSelectionTable || Reference_ID == DisplayType.ChosenMultipleSelectionSearch)
|
||||
{
|
||||
String columnName = TableName + "." + ParameterName;
|
||||
if (columnName.endsWith("_ID"))
|
||||
query.addRestriction(DB.inClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info);
|
||||
else
|
||||
query.addRestriction(DB.intersectClauseForCSV(columnName, P_String), MQuery.EQUAL, Name, Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (P_String.indexOf('%') == -1)
|
||||
query.addRestriction(ParameterName, MQuery.EQUAL,
|
||||
|
@ -173,6 +192,7 @@ public class MQuery implements Serializable
|
|||
query.addRestriction(ParameterName, MQuery.LIKE,
|
||||
P_String, Name, Info);
|
||||
}
|
||||
}
|
||||
else
|
||||
query.addRangeRestriction(ParameterName,
|
||||
P_String, P_String_To, Name, Info, Info_To);
|
||||
|
@ -235,7 +255,6 @@ public class MQuery implements Serializable
|
|||
return query;
|
||||
} // get
|
||||
|
||||
|
||||
/**
|
||||
* Get Zoom Column Name.
|
||||
* Converts Synonyms like SalesRep_ID to AD_User_ID
|
||||
|
@ -632,6 +651,20 @@ public class MQuery implements Serializable
|
|||
m_newRecord = whereClause.equals(NEWRECORD);
|
||||
} // addRestriction
|
||||
|
||||
public void addRestriction (String whereClause, String Operator, String InfoName, String InfoDisplay)
|
||||
{
|
||||
if (whereClause == null || whereClause.trim().length() == 0)
|
||||
return;
|
||||
Restriction r = new Restriction (whereClause, true, 0);
|
||||
r.Operator = Operator;
|
||||
if (InfoName != null)
|
||||
r.InfoName = InfoName;
|
||||
if (InfoDisplay != null)
|
||||
r.InfoDisplay = InfoDisplay.trim();
|
||||
m_list.add(r);
|
||||
m_newRecord = whereClause.equals(NEWRECORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* New Record Query
|
||||
* @return true if new record query
|
||||
|
|
|
@ -96,6 +96,9 @@ public class SystemIDs
|
|||
public final static int REFERENCE_DATATYPE_ASSIGNMENT = 33;
|
||||
public final static int REFERENCE_DATATYPE_BINARY = 23;
|
||||
public final static int REFERENCE_DATATYPE_BUTTON = 28;
|
||||
public final static int REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_LIST = 200161;
|
||||
public final static int REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_TABLE = 200162;
|
||||
public final static int REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_SEARCH = 200163;
|
||||
public final static int REFERENCE_DATATYPE_COLOR = 27;
|
||||
public final static int REFERENCE_DATATYPE_COSTPRICE = 37;
|
||||
public final static int REFERENCE_DATATYPE_DATE = 15;
|
||||
|
|
|
@ -2578,4 +2578,57 @@ public final class DB
|
|||
return ProxyFactory.newCPreparedStatement(resultSetType, resultSetConcurrency, sql, trxName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param columnName
|
||||
* @param csv comma separated value
|
||||
* @return IN clause
|
||||
*/
|
||||
public static String inClauseForCSV(String columnName, String csv)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(columnName).append(" IN (");
|
||||
String[] values = csv.split("[,]");
|
||||
for(int i = 0; i < values.length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
builder.append(",");
|
||||
String key = values[i];
|
||||
if (columnName.endsWith("_ID"))
|
||||
{
|
||||
builder.append(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key.startsWith("\"") && key.endsWith("\""))
|
||||
{
|
||||
key = key.substring(1, key.length()-1);
|
||||
}
|
||||
builder.append(TO_STRING(key));
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param columnName
|
||||
* @param csv
|
||||
* @return subset sql clause
|
||||
*/
|
||||
public static String subsetClauseForCSV(String columnName, String csv)
|
||||
{
|
||||
return getDatabase().subsetClauseForCSV(columnName, csv);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param columnName
|
||||
* @param csv
|
||||
* @return intersect sql clause
|
||||
*/
|
||||
public static String intersectClauseForCSV(String columnName, String csv)
|
||||
{
|
||||
return getDatabase().intersectClauseForCSV(columnName, csv);
|
||||
}
|
||||
} // DB
|
||||
|
|
|
@ -21,6 +21,9 @@ import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_AMOUNT;
|
|||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_ASSIGNMENT;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_BINARY;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_BUTTON;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_LIST;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_TABLE;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_SEARCH;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_COLOR;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_COSTPRICE;
|
||||
import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_DATE;
|
||||
|
@ -156,6 +159,12 @@ public final class DisplayType
|
|||
|
||||
public static final int MultipleSelectionGrid = REFERENCE_DATATYPE_MULTIPLE_SELECTION_GRID;
|
||||
|
||||
public static final int ChosenMultipleSelectionList = REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_LIST;
|
||||
|
||||
public static final int ChosenMultipleSelectionTable = REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_TABLE;
|
||||
|
||||
public static final int ChosenMultipleSelectionSearch = REFERENCE_DATATYPE_CHOSEN_MULTIPLE_SELECTION_SEARCH;
|
||||
|
||||
/**
|
||||
* - New Display Type
|
||||
INSERT INTO AD_REFERENCE
|
||||
|
@ -272,7 +281,10 @@ public final class DisplayType
|
|||
|| displayType == FilePath || displayType == FileName
|
||||
|| displayType == URL || displayType == PrinterName
|
||||
|| displayType == SingleSelectionGrid || displayType == Color
|
||||
|| displayType == MultipleSelectionGrid)
|
||||
|| displayType == MultipleSelectionGrid
|
||||
|| displayType == ChosenMultipleSelectionList
|
||||
|| displayType == ChosenMultipleSelectionTable
|
||||
|| displayType == ChosenMultipleSelectionSearch)
|
||||
return true;
|
||||
|
||||
List<IDisplayTypeFactory> factoryList = Service.locator().list(IDisplayTypeFactory.class).getServices();
|
||||
|
@ -312,7 +324,10 @@ public final class DisplayType
|
|||
public static boolean isLookup(int displayType)
|
||||
{
|
||||
if (displayType == List || displayType == Table
|
||||
|| displayType == TableDir || displayType == Search)
|
||||
|| displayType == TableDir || displayType == Search
|
||||
|| displayType == ChosenMultipleSelectionTable
|
||||
|| displayType == ChosenMultipleSelectionSearch
|
||||
|| displayType == ChosenMultipleSelectionList)
|
||||
return true;
|
||||
|
||||
List<IDisplayTypeFactory> factoryList = Service.locator().list(IDisplayTypeFactory.class).getServices();
|
||||
|
|
|
@ -91,6 +91,10 @@ Export-Package: fi.jawsy.jawwa.zk.atmosphere,
|
|||
org.adempiere.webui.window,
|
||||
org.zkforge.ckez,
|
||||
org.zkforge.keylistener,
|
||||
web.chosenbox.img,
|
||||
web.js.chosenbox,
|
||||
web.js.chosenbox.css,
|
||||
web.js.chosenbox.mold,
|
||||
web.ckez.html,
|
||||
web.ckez.img,
|
||||
web.js.ckez,
|
||||
|
|
|
@ -33,6 +33,17 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
|
|||
</mold>
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<component-name>chosenbox</component-name>
|
||||
<component-class>org.zkoss.addon.chosenbox.Chosenbox</component-class>
|
||||
<widget-class>chosenbox.Chosenbox</widget-class>
|
||||
<mold>
|
||||
<mold-name>default</mold-name>
|
||||
<mold-uri>mold/chosenbox.js</mold-uri>
|
||||
<css-uri>css/chosenbox.css.dsp</css-uri>
|
||||
</mold>
|
||||
</component>
|
||||
|
||||
<javascript src="/js/calc.js" charset="UTF-8"/>
|
||||
<javascript src="/js/layout.js" charset="UTF-8"/>
|
||||
<javascript src="/js/report.js" charset="UTF-8"/>
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/******************************************************************************
|
||||
* Project: Trek Global ERP *
|
||||
* Copyright (C) 2009-2018 Trek Global Corporation *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.webui.component;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
import org.adempiere.webui.LayoutUtils;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
import org.zkoss.addon.chosenbox.Chosenbox;
|
||||
import org.zkoss.zk.ui.Page;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zul.Div;
|
||||
|
||||
/**
|
||||
* @author Low Heng Sin
|
||||
*/
|
||||
public class ChosenSearchBox extends Div {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3152111756471436612L;
|
||||
protected PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(
|
||||
this);
|
||||
protected Chosenbox<ValueNamePair> chosenbox;
|
||||
protected Button btn;
|
||||
|
||||
public ChosenSearchBox() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageSrc
|
||||
*/
|
||||
public void setButtonImage(String imageSrc) {
|
||||
btn.setImage(imageSrc);
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
chosenbox = new Chosenbox<>();
|
||||
chosenbox.setSclass("editor-input");
|
||||
chosenbox.setWidth("100%");
|
||||
appendChild(chosenbox);
|
||||
btn = new Button();
|
||||
btn.setTabindex(-1);
|
||||
btn.setHflex("0");
|
||||
btn.setSclass("editor-button");
|
||||
appendChild(btn);
|
||||
|
||||
LayoutUtils.addSclass("editor-box", this);
|
||||
setTableEditorMode(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return chosenbox component
|
||||
*/
|
||||
public Chosenbox<ValueNamePair> getChosenbox() {
|
||||
return chosenbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabled
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
chosenbox.setDisabled(!enabled);
|
||||
btn.setEnabled(enabled);
|
||||
btn.setVisible(enabled);
|
||||
if (enabled) {
|
||||
if (btn.getParent() != chosenbox.getParent())
|
||||
btn.setParent(chosenbox.getParent());
|
||||
} else {
|
||||
if (btn.getParent() != null)
|
||||
btn.detach();
|
||||
}
|
||||
if (enabled) {
|
||||
LayoutUtils.removeSclass("editor-input-disd", chosenbox);
|
||||
} else {
|
||||
LayoutUtils.addSclass("editor-input-disd", chosenbox);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return btn.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param evtnm
|
||||
* @param listener
|
||||
*/
|
||||
public boolean addEventListener(String evtnm, EventListener<?> listener) {
|
||||
if (Events.ON_CLICK.equals(evtnm)) {
|
||||
return btn.addEventListener(evtnm, listener);
|
||||
} else {
|
||||
return chosenbox.addEventListener(evtnm, listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param l
|
||||
*/
|
||||
public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
m_propertyChangeListeners.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tooltiptext
|
||||
*/
|
||||
public void setToolTipText(String tooltiptext) {
|
||||
chosenbox.setTooltiptext(tooltiptext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Button
|
||||
*/
|
||||
public Button getButton() {
|
||||
return btn;
|
||||
}
|
||||
|
||||
public void setTableEditorMode(boolean flag) {
|
||||
if (flag) {
|
||||
setHflex("0");
|
||||
LayoutUtils.addSclass("grid-editor-input", chosenbox);
|
||||
LayoutUtils.addSclass("grid-editor-button", btn);
|
||||
} else {
|
||||
setHflex("1");
|
||||
LayoutUtils.removeSclass("grid-editor-input", chosenbox);
|
||||
LayoutUtils.removeSclass("grid-editor-button", btn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageAttached(Page newpage, Page oldpage) {
|
||||
super.onPageAttached(newpage, oldpage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,560 @@
|
|||
/******************************************************************************
|
||||
* Project: Trek Global ERP *
|
||||
* Copyright (C) 2009-2018 Trek Global Corporation *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.webui.editor;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.adempiere.webui.ValuePreference;
|
||||
import org.adempiere.webui.event.ContextMenuEvent;
|
||||
import org.adempiere.webui.event.ContextMenuListener;
|
||||
import org.adempiere.webui.event.ValueChangeEvent;
|
||||
import org.adempiere.webui.window.WFieldRecordInfo;
|
||||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.Lookup;
|
||||
import org.compiere.model.MLookup;
|
||||
import org.compiere.util.CCache;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.CacheMgt;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
import org.compiere.util.Util;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
import org.zkoss.addon.chosenbox.Chosenbox;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.Page;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zk.ui.util.DesktopCleanup;
|
||||
import org.zkoss.zul.ListModelList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class WChosenboxListEditor extends WEditor implements ContextMenuListener
|
||||
{
|
||||
public final static String[] LISTENER_EVENTS = {Events.ON_SELECT};
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final CLogger logger;
|
||||
|
||||
static
|
||||
{
|
||||
logger = CLogger.getCLogger(WTableDirEditor.class);
|
||||
}
|
||||
|
||||
private Lookup lookup;
|
||||
private Object oldValue;
|
||||
|
||||
private CCacheListener tableCacheListener;
|
||||
|
||||
private boolean onselecting = false;
|
||||
|
||||
private ListModelList<ValueNamePair> model = new ListModelList<>();
|
||||
|
||||
public WChosenboxListEditor(GridField gridField)
|
||||
{
|
||||
this(new ChosenboxEditor(), gridField);
|
||||
}
|
||||
|
||||
private WChosenboxListEditor(Component comp, GridField gridField)
|
||||
{
|
||||
super(comp, gridField);
|
||||
lookup = gridField.getLookup();
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for use if a grid field is unavailable
|
||||
*
|
||||
* @param lookup Store of selectable data
|
||||
* @param label column name (not displayed)
|
||||
* @param description description of component
|
||||
* @param mandatory whether a selection must be made
|
||||
* @param readonly whether or not the editor is read only
|
||||
* @param updateable whether the editor contents can be changed
|
||||
*/
|
||||
public WChosenboxListEditor(Lookup lookup, String label, String description, boolean mandatory, boolean readonly, boolean updateable)
|
||||
{
|
||||
this(lookup, label, description, mandatory, readonly, updateable, false);
|
||||
}
|
||||
|
||||
public WChosenboxListEditor(Lookup lookup, String label, String description, boolean mandatory, boolean readonly, boolean updateable, boolean autocomplete)
|
||||
{
|
||||
this(new ChosenboxEditor(), lookup, label, description, mandatory, readonly, updateable);
|
||||
}
|
||||
|
||||
private WChosenboxListEditor(Component comp, Lookup lookup, String label, String description, boolean mandatory, boolean readonly, boolean updateable)
|
||||
{
|
||||
super(comp, label, description, mandatory, readonly, updateable);
|
||||
|
||||
if (lookup == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Lookup cannot be null");
|
||||
}
|
||||
|
||||
this.lookup = lookup;
|
||||
super.setColumnName(lookup.getColumnName());
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* For ease of porting swing form
|
||||
* @param columnName
|
||||
* @param mandatory
|
||||
* @param isReadOnly
|
||||
* @param isUpdateable
|
||||
* @param lookup
|
||||
*/
|
||||
public WChosenboxListEditor(String columnName, boolean mandatory, boolean isReadOnly, boolean isUpdateable, Lookup lookup)
|
||||
{
|
||||
this(columnName, mandatory, isReadOnly, isUpdateable, lookup, false);
|
||||
}
|
||||
|
||||
public WChosenboxListEditor(String columnName, boolean mandatory, boolean isReadOnly, boolean isUpdateable, Lookup lookup, boolean autocomplete)
|
||||
{
|
||||
this(new ChosenboxEditor(), columnName, mandatory, isReadOnly, isUpdateable, lookup);
|
||||
}
|
||||
|
||||
private WChosenboxListEditor(Component comp, String columnName, boolean mandatory, boolean isReadOnly, boolean isUpdateable, Lookup lookup)
|
||||
{
|
||||
super(comp, columnName, null, null, mandatory, isReadOnly, isUpdateable);
|
||||
if (lookup == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Lookup cannot be null");
|
||||
}
|
||||
this.lookup = lookup;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
getComponent().setHflex("true");
|
||||
getComponent().editor = this;
|
||||
getComponent().setModel(model);
|
||||
|
||||
if (lookup != null)
|
||||
{
|
||||
lookup.setMandatory(true);
|
||||
|
||||
//no need to refresh readonly lookup
|
||||
if (isReadWrite())
|
||||
{
|
||||
refreshLookup();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateModel();
|
||||
}
|
||||
}
|
||||
|
||||
if (gridField != null)
|
||||
{
|
||||
popupMenu = new WEditorPopupMenu(false, true, isShowPreference(), false, false, false, lookup);
|
||||
addChangeLogMenu(popupMenu);
|
||||
}
|
||||
}
|
||||
|
||||
protected void refreshLookup() {
|
||||
lookup.refresh();
|
||||
updateModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay()
|
||||
{
|
||||
StringBuilder display = new StringBuilder();
|
||||
LinkedHashSet<ValueNamePair> selected = getComponent().getSelectedObjects();
|
||||
if (selected != null && selected.size() > 0)
|
||||
{
|
||||
for(ValueNamePair pair : selected)
|
||||
{
|
||||
if (display.length() > 0)
|
||||
display.append(", ");
|
||||
display.append(pair.getName());
|
||||
}
|
||||
}
|
||||
return display.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
private String getValueFromComponent()
|
||||
{
|
||||
StringBuilder retVal = new StringBuilder();
|
||||
LinkedHashSet<ValueNamePair> selected = getComponent().getSelectedObjects();
|
||||
if (selected != null && selected.size() > 0)
|
||||
{
|
||||
for(ValueNamePair pair : selected)
|
||||
{
|
||||
if (retVal.length() > 0)
|
||||
retVal.append(",");
|
||||
StringBuilder builder = new StringBuilder(pair.getValue());
|
||||
if (builder.indexOf(",") >= 0)
|
||||
{
|
||||
builder.insert(0, "\"");
|
||||
builder.append("\"");
|
||||
}
|
||||
retVal.append(builder.toString());
|
||||
}
|
||||
}
|
||||
return retVal.length() > 0 ? retVal.toString() : null;
|
||||
}
|
||||
|
||||
public void setValue(Object value)
|
||||
{
|
||||
if (onselecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
String[] values = ((String)value).split("[,]");
|
||||
Set<ValueNamePair> selected = new LinkedHashSet<>();
|
||||
for (String key : values) {
|
||||
if (!Util.isEmpty(key)) {
|
||||
if (key.startsWith("\"") && key.endsWith("\"")) {
|
||||
key = key.substring(1, key.length()-1);
|
||||
}
|
||||
String name = lookup.getDisplay(key);
|
||||
ValueNamePair pair = new ValueNamePair(key, name);
|
||||
selected.add(pair);
|
||||
}
|
||||
}
|
||||
getComponent().setSelectedObjects(selected);
|
||||
if (getComponent().getSelectedObjects().size() != selected.size())
|
||||
{
|
||||
Object curValue = oldValue;
|
||||
oldValue = value;
|
||||
|
||||
if (isReadWrite() && lookup != null)
|
||||
{
|
||||
refreshLookup();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateModel();
|
||||
}
|
||||
getComponent().setSelectedObjects(selected);
|
||||
|
||||
//still not in list, reset to zero
|
||||
if (getComponent().getSelectedObjects().size() != selected.size())
|
||||
{
|
||||
getComponent().setSelectedObjects(new LinkedHashSet<ValueNamePair>());
|
||||
if (curValue == null)
|
||||
curValue = value;
|
||||
ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), curValue, null);
|
||||
super.fireValueChange(changeEvent);
|
||||
oldValue = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldValue = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getComponent().setSelectedObjects(new LinkedHashSet<ValueNamePair>());
|
||||
oldValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChosenboxEditor getComponent() {
|
||||
return (ChosenboxEditor) component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadWrite() {
|
||||
return getComponent().isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadWrite(boolean readWrite) {
|
||||
getComponent().setEnabled(readWrite);
|
||||
}
|
||||
|
||||
private void updateModel()
|
||||
{
|
||||
List<ValueNamePair> list = new ArrayList<>();
|
||||
|
||||
if (isReadWrite())
|
||||
{
|
||||
if (lookup != null)
|
||||
{
|
||||
int size = lookup.getSize();
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
Object obj = lookup.getElementAt(i);
|
||||
if (obj instanceof KeyNamePair)
|
||||
{
|
||||
KeyNamePair lookupKNPair = (KeyNamePair) obj;
|
||||
ValueNamePair vnp = new ValueNamePair(Integer.toString(lookupKNPair.getKey()), lookupKNPair.getName());
|
||||
list.add(vnp);
|
||||
}
|
||||
else if (obj instanceof ValueNamePair)
|
||||
{
|
||||
ValueNamePair lookupKNPair = (ValueNamePair) obj;
|
||||
list.add(lookupKNPair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lookup != null && oldValue != null)
|
||||
{
|
||||
String[] values = ((String)oldValue).split("[,]");
|
||||
List<ValueNamePair> selected = new ArrayList<>();
|
||||
for (String key : values) {
|
||||
if (!Util.isEmpty(key)) {
|
||||
if (key.startsWith("\"") && key.endsWith("\"")) {
|
||||
key = key.substring(1, key.length()-1);
|
||||
}
|
||||
String name = lookup.getDisplay(key);
|
||||
ValueNamePair pair = new ValueNamePair(key, name);
|
||||
selected.add(pair);
|
||||
}
|
||||
}
|
||||
list = selected;
|
||||
}
|
||||
}
|
||||
|
||||
model.clear();
|
||||
model.addAll(list);
|
||||
}
|
||||
|
||||
public void onEvent(Event event)
|
||||
{
|
||||
if (Events.ON_SELECT.equalsIgnoreCase(event.getName()))
|
||||
{
|
||||
try {
|
||||
onselecting = true;
|
||||
Object newValue = getValueFromComponent();
|
||||
if (isValueChange(newValue)) {
|
||||
try {
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(true);
|
||||
ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue);
|
||||
super.fireValueChange(changeEvent);
|
||||
oldValue = newValue;
|
||||
} finally {
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
onselecting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValueChange(Object newValue) {
|
||||
return (oldValue == null && newValue != null) || (oldValue != null && newValue == null)
|
||||
|| ((oldValue != null && newValue != null) && !oldValue.equals(newValue));
|
||||
}
|
||||
|
||||
public String[] getEvents()
|
||||
{
|
||||
return LISTENER_EVENTS;
|
||||
}
|
||||
|
||||
public void actionRefresh()
|
||||
{
|
||||
if (lookup != null)
|
||||
{
|
||||
Object curValue = getValue();
|
||||
|
||||
if (isReadWrite())
|
||||
refreshLookup();
|
||||
else
|
||||
updateModel();
|
||||
if (curValue != null)
|
||||
{
|
||||
setValue(curValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Lookup getLookup()
|
||||
{
|
||||
return lookup;
|
||||
}
|
||||
|
||||
public void onMenu(ContextMenuEvent evt)
|
||||
{
|
||||
if (WEditorPopupMenu.REQUERY_EVENT.equals(evt.getContextEvent()))
|
||||
{
|
||||
actionRefresh();
|
||||
}
|
||||
else if (WEditorPopupMenu.PREFERENCE_EVENT.equals(evt.getContextEvent()))
|
||||
{
|
||||
if (isShowPreference())
|
||||
ValuePreference.start (getComponent(), this.getGridField(), getValue());
|
||||
return;
|
||||
}
|
||||
else if (WEditorPopupMenu.CHANGE_LOG_EVENT.equals(evt.getContextEvent()))
|
||||
{
|
||||
WFieldRecordInfo.start(gridField);
|
||||
}
|
||||
}
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt)
|
||||
{
|
||||
if ("FieldValue".equals(evt.getPropertyName()))
|
||||
{
|
||||
setValue(evt.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dynamicDisplay(Properties ctx)
|
||||
{
|
||||
if (lookup instanceof MLookup)
|
||||
{
|
||||
((MLookup) lookup).getLookupInfo().ctx = ctx;
|
||||
}
|
||||
if ((lookup != null) && (!lookup.isValidated() || !lookup.isLoaded()
|
||||
|| (isReadWrite() && lookup.getSize() != getComponent().getModel().getSize())))
|
||||
this.actionRefresh();
|
||||
|
||||
super.dynamicDisplay(ctx);
|
||||
}
|
||||
|
||||
private void createCacheListener() {
|
||||
if (lookup != null) {
|
||||
String columnName = lookup.getColumnName();
|
||||
int dotIndex = columnName.indexOf(".");
|
||||
if (dotIndex > 0) {
|
||||
String tableName = columnName.substring(0, dotIndex);
|
||||
tableCacheListener = new CCacheListener(tableName, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final static class ChosenboxEditor extends Chosenbox<ValueNamePair> {
|
||||
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = 7777300782255405327L;
|
||||
private DesktopCleanup listener = null;
|
||||
private WChosenboxListEditor editor = null;
|
||||
|
||||
protected ChosenboxEditor() {
|
||||
}
|
||||
|
||||
public void setEnabled(boolean readWrite) {
|
||||
setDisabled(readWrite==false);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return isDisabled() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPage(Page page) {
|
||||
super.setPage(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageAttached(Page newpage, Page oldpage) {
|
||||
super.onPageAttached(newpage, oldpage);
|
||||
if (editor != null && editor.tableCacheListener == null) {
|
||||
editor.createCacheListener();
|
||||
if (listener == null) {
|
||||
listener = new DesktopCleanup() {
|
||||
@Override
|
||||
public void cleanup(Desktop desktop) throws Exception {
|
||||
ChosenboxEditor.this.cleanup();
|
||||
}
|
||||
};
|
||||
newpage.getDesktop().addListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageDetached(Page page) {
|
||||
super.onPageDetached(page);
|
||||
if (listener != null && page.getDesktop() != null)
|
||||
page.getDesktop().removeListener(listener);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected void cleanup() {
|
||||
if (editor != null && editor.tableCacheListener != null) {
|
||||
CacheMgt.get().unregister(editor.tableCacheListener);
|
||||
editor.tableCacheListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CCacheListener extends CCache<String, Object> {
|
||||
/**
|
||||
* generated serial
|
||||
*/
|
||||
private static final long serialVersionUID = 3543247404379028327L;
|
||||
private WChosenboxListEditor editor;
|
||||
|
||||
protected CCacheListener(String tableName, WChosenboxListEditor editor) {
|
||||
super(tableName, tableName, 0, true);
|
||||
this.editor = editor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int reset() {
|
||||
if (editor.getComponent().getDesktop() != null && editor.isReadWrite()) {
|
||||
refreshLookupList();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void refreshLookupList() {
|
||||
Executions.schedule(editor.getComponent().getDesktop(), new EventListener<Event>() {
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
try {
|
||||
if (editor.isReadWrite())
|
||||
editor.actionRefresh();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}, new Event("onResetLookupList"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newRecord(int record_ID) {
|
||||
if (editor.getComponent().getDesktop() != null && editor.isReadWrite()) {
|
||||
refreshLookupList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,793 @@
|
|||
/******************************************************************************
|
||||
* Project: Trek Global ERP *
|
||||
* Copyright (C) 2009-2018 Trek Global Corporation *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.webui.editor;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.webui.ValuePreference;
|
||||
import org.adempiere.webui.apps.AEnv;
|
||||
import org.adempiere.webui.component.ChosenSearchBox;
|
||||
import org.adempiere.webui.event.ContextMenuEvent;
|
||||
import org.adempiere.webui.event.ContextMenuListener;
|
||||
import org.adempiere.webui.event.DialogEvents;
|
||||
import org.adempiere.webui.event.ValueChangeEvent;
|
||||
import org.adempiere.webui.factory.InfoManager;
|
||||
import org.adempiere.webui.panel.IHelpContext;
|
||||
import org.adempiere.webui.panel.InfoPanel;
|
||||
import org.adempiere.webui.part.WindowContainer;
|
||||
import org.adempiere.webui.session.SessionManager;
|
||||
import org.adempiere.webui.theme.ThemeManager;
|
||||
import org.adempiere.webui.window.WFieldRecordInfo;
|
||||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.Lookup;
|
||||
import org.compiere.model.MLookup;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.X_AD_CtxHelp;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zul.ListModel;
|
||||
import org.zkoss.zul.ListModelList;
|
||||
import org.zkoss.zul.ListSubModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class WChosenboxSearchEditor extends WEditor implements ContextMenuListener
|
||||
{
|
||||
private static final String[] LISTENER_EVENTS = {Events.ON_CLICK, Events.ON_SELECT};
|
||||
private Lookup lookup;
|
||||
private String m_tableName = null;
|
||||
private String m_keyColumnName = null;
|
||||
private String columnName;
|
||||
private String value;
|
||||
private InfoPanel infoPanel = null;
|
||||
private String imageUrl;
|
||||
private MyListModel model = new MyListModel();
|
||||
|
||||
private static CLogger log = CLogger.getCLogger(WChosenboxSearchEditor.class);
|
||||
private boolean onselecting;
|
||||
|
||||
public WChosenboxSearchEditor (GridField gridField)
|
||||
{
|
||||
super(new ChosenSearchBox(), gridField);
|
||||
|
||||
lookup = gridField.getLookup();
|
||||
|
||||
if (lookup != null)
|
||||
columnName = lookup.getColumnName();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChosenSearchBox getComponent() {
|
||||
return (ChosenSearchBox) super.getComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadWrite() {
|
||||
return getComponent().isEnabled();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setReadWrite(boolean readWrite) {
|
||||
getComponent().setEnabled(readWrite);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for use if a grid field is unavailable
|
||||
*
|
||||
* @param lookup Store of selectable data
|
||||
* @param label column name (not displayed)
|
||||
* @param description description of component
|
||||
* @param mandatory whether a selection must be made
|
||||
* @param readonly whether or not the editor is read only
|
||||
* @param updateable whether the editor contents can be changed
|
||||
*/
|
||||
public WChosenboxSearchEditor (Lookup lookup, String label, String description, boolean mandatory, boolean readonly, boolean updateable)
|
||||
{
|
||||
super(new ChosenSearchBox(), label, description, mandatory, readonly, updateable);
|
||||
|
||||
if (lookup == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Lookup cannot be null");
|
||||
}
|
||||
|
||||
this.lookup = lookup;
|
||||
columnName = lookup.getColumnName();
|
||||
super.setColumnName(columnName);
|
||||
init();
|
||||
}
|
||||
|
||||
public WChosenboxSearchEditor(String columnName, boolean mandatory, boolean readonly, boolean updateable,
|
||||
Lookup lookup)
|
||||
{
|
||||
super(new ChosenSearchBox(), null, null, mandatory, readonly, updateable);
|
||||
|
||||
if (lookup == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Lookup cannot be null");
|
||||
}
|
||||
|
||||
this.lookup = lookup;
|
||||
this.columnName = columnName;
|
||||
super.setColumnName(columnName);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* initialise editor
|
||||
* @param columnName columnName
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
columnName = this.getColumnName();
|
||||
imageUrl = ThemeManager.getThemeResource("images/PickOpen16.png");
|
||||
if (lookup instanceof MLookup)
|
||||
{
|
||||
MLookup mlookup = (MLookup) lookup;
|
||||
if ("C_BPartner_ID".equals(mlookup.getLookupInfo().KeyColumn))
|
||||
{
|
||||
imageUrl = ThemeManager.getThemeResource("images/BPartner16.png");
|
||||
}
|
||||
else if ("M_Product_ID".equals(mlookup.getLookupInfo().KeyColumn))
|
||||
{
|
||||
imageUrl = ThemeManager.getThemeResource("images/Product16.png");
|
||||
}
|
||||
}
|
||||
popupMenu = new WEditorPopupMenu(false, true, isShowPreference(), false, false, false, lookup);
|
||||
getComponent().getButton().setImage(imageUrl);
|
||||
getComponent().getChosenbox().setModel(model);
|
||||
|
||||
addChangeLogMenu(popupMenu);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Object value)
|
||||
{
|
||||
if (onselecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != null && value instanceof String && !Util.isEmpty((String) value, true))
|
||||
{
|
||||
String[] values = ((String)value).split("[,]");
|
||||
Set<ValueNamePair> selected = new LinkedHashSet<>();
|
||||
for (String key : values) {
|
||||
if (!Util.isEmpty(key)) {
|
||||
if (key.startsWith("\"") && key.endsWith("\"")) {
|
||||
key = key.substring(1, key.length()-1);
|
||||
}
|
||||
String name = lookup.getDisplay(key);
|
||||
ValueNamePair pair = new ValueNamePair(key, name);
|
||||
selected.add(pair);
|
||||
}
|
||||
}
|
||||
model.clear();
|
||||
model.addAll(selected);
|
||||
getComponent().getChosenbox().setSelectedObjects(selected);
|
||||
this.value = (String)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.clear();
|
||||
getComponent().getChosenbox().setSelectedObjects(new LinkedHashSet<ValueNamePair>());
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
private String getValueFromComponent()
|
||||
{
|
||||
StringBuilder retVal = new StringBuilder();
|
||||
LinkedHashSet<ValueNamePair> selected = getComponent().getChosenbox().getSelectedObjects();
|
||||
if (selected != null && selected.size() > 0)
|
||||
{
|
||||
for(ValueNamePair pair : selected)
|
||||
{
|
||||
if (retVal.length() > 0)
|
||||
retVal.append(",");
|
||||
StringBuilder builder = new StringBuilder(pair.getValue());
|
||||
if (builder.indexOf(",") >= 0)
|
||||
{
|
||||
builder.insert(0, "\"");
|
||||
builder.append("\"");
|
||||
}
|
||||
retVal.append(builder.toString());
|
||||
}
|
||||
}
|
||||
return retVal.length() > 0 ? retVal.toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplay()
|
||||
{
|
||||
StringBuilder display = new StringBuilder();
|
||||
LinkedHashSet<ValueNamePair> selected = getComponent().getChosenbox().getSelectedObjects();
|
||||
if (selected != null && selected.size() > 0)
|
||||
{
|
||||
for(ValueNamePair pair : selected)
|
||||
{
|
||||
if (display.length() > 0)
|
||||
display.append(", ");
|
||||
display.append(pair.getName());
|
||||
}
|
||||
}
|
||||
return display.toString();
|
||||
}
|
||||
|
||||
public void onEvent(Event e)
|
||||
{
|
||||
if (Events.ON_CLICK.equals(e.getName()))
|
||||
{
|
||||
if (infoPanel != null)
|
||||
{
|
||||
infoPanel.detach();
|
||||
infoPanel = null;
|
||||
}
|
||||
actionButton();
|
||||
}
|
||||
else if (Events.ON_SELECT.equalsIgnoreCase(e.getName()))
|
||||
{
|
||||
try {
|
||||
onselecting = true;
|
||||
String newValue = getValueFromComponent();
|
||||
if (isValueChange(newValue)) {
|
||||
try {
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(true);
|
||||
ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), value, newValue);
|
||||
super.fireValueChange(changeEvent);
|
||||
value = newValue;
|
||||
} finally {
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
onselecting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValueChange(Object newValue) {
|
||||
return (value == null && newValue != null) || (value != null && newValue == null)
|
||||
|| ((value != null && newValue != null) && !value.equals(newValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt)
|
||||
{
|
||||
if ("FieldValue".equals(evt.getPropertyName()))
|
||||
{
|
||||
setValue(evt.getNewValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void onMenu(ContextMenuEvent evt)
|
||||
{
|
||||
if (WEditorPopupMenu.PREFERENCE_EVENT.equals(evt.getContextEvent()))
|
||||
{
|
||||
if (isShowPreference())
|
||||
ValuePreference.start (getComponent(), this.getGridField(), getValue());
|
||||
return;
|
||||
}
|
||||
else if (WEditorPopupMenu.CHANGE_LOG_EVENT.equals(evt.getContextEvent()))
|
||||
{
|
||||
WFieldRecordInfo.start(gridField);
|
||||
}
|
||||
}
|
||||
|
||||
private void processSelectedKeys (Object value)
|
||||
{
|
||||
if (log.isLoggable(Level.FINE))
|
||||
log.fine("Value=" + value);
|
||||
|
||||
try
|
||||
{
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(true);
|
||||
|
||||
String newValue = this.value;
|
||||
if (newValue == null)
|
||||
{
|
||||
if (value instanceof Object[])
|
||||
{
|
||||
if (((Object[])value).length > 0)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(Object obj : (Object[])value)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
if (builder.length() > 0)
|
||||
builder.append(",");
|
||||
builder.append(obj.toString());
|
||||
}
|
||||
}
|
||||
newValue = builder.toString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = value != null ? value.toString() : null;
|
||||
}
|
||||
}
|
||||
else if (value != null)
|
||||
{
|
||||
if (value instanceof Object[])
|
||||
{
|
||||
if (((Object[])value).length > 0)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(newValue);
|
||||
for(Object obj : (Object[])value)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
if (builder.length() > 0)
|
||||
builder.append(",");
|
||||
builder.append(obj.toString());
|
||||
}
|
||||
}
|
||||
newValue = builder.toString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = newValue + "," + value.toString();
|
||||
}
|
||||
}
|
||||
fireValueChangeEvent(newValue);
|
||||
|
||||
// is the value updated ?
|
||||
boolean updated = false;
|
||||
if (newValue == null && getValue() == null) {
|
||||
updated = true;
|
||||
} else if (newValue != null && newValue.equals(getValue())) {
|
||||
updated = true;
|
||||
}
|
||||
if (!updated)
|
||||
{
|
||||
setValue(newValue);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gridField != null)
|
||||
gridField.setLookupEditorSettingValue(false);
|
||||
}
|
||||
|
||||
} // actionCombo
|
||||
|
||||
|
||||
protected void fireValueChangeEvent(Object newValue) {
|
||||
ValueChangeEvent evt = new ValueChangeEvent(this, this.getColumnName(), getValue(), newValue);
|
||||
// -> ADTabpanel - valuechange
|
||||
fireValueChange(evt);
|
||||
}
|
||||
|
||||
private void actionButton()
|
||||
{
|
||||
if (lookup == null)
|
||||
return; // leave button disabled
|
||||
|
||||
/**
|
||||
* Three return options:
|
||||
* - Value Selected & OK pressed => store result => result has value
|
||||
* - Cancel pressed => store null => result == null && cancelled
|
||||
* - Window closed -> ignore => result == null && !cancalled
|
||||
*/
|
||||
|
||||
// Validation
|
||||
String whereClause = getWhereClause();
|
||||
|
||||
if (m_tableName == null) // sets table name & key column
|
||||
getDirectAccessSQL("*");
|
||||
|
||||
final InfoPanel ip = InfoManager.create(lookup, gridField, m_tableName, m_keyColumnName, null, false, whereClause);
|
||||
if (ip != null)
|
||||
showInfoPanel(ip);
|
||||
}
|
||||
|
||||
|
||||
protected void showInfoPanel(final InfoPanel ip) {
|
||||
ip.setVisible(true);
|
||||
ip.setStyle("border: 2px");
|
||||
ip.setClosable(true);
|
||||
infoPanel = ip;
|
||||
ip.addEventListener(DialogEvents.ON_WINDOW_CLOSE, new EventListener<Event>() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
Component component = SessionManager.getAppDesktop().getActiveWindow();
|
||||
if (component instanceof IHelpContext)
|
||||
Events.sendEvent(new Event(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, component));
|
||||
else
|
||||
SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0);
|
||||
|
||||
boolean cancelled = ip.isCancelled();
|
||||
Object[] result = ip.getSelectedKeys();
|
||||
|
||||
infoPanel = null;
|
||||
// Result
|
||||
if (!cancelled && result != null && result.length > 0)
|
||||
{
|
||||
//ensure data binding happen
|
||||
if (result.length > 1)
|
||||
processSelectedKeys (result);
|
||||
else
|
||||
processSelectedKeys (result[0]);
|
||||
}
|
||||
getComponent().getChosenbox().focus();
|
||||
}
|
||||
});
|
||||
ip.setId(ip.getTitle()+"_"+ip.getWindowNo());
|
||||
AEnv.showWindow(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Access SQL for Search.
|
||||
* The SQL returns the ID of the value entered
|
||||
* Also sets m_tableName and m_keyColumnName
|
||||
* @param text uppercase text for LIKE comparison
|
||||
* @return sql or ""
|
||||
* Example
|
||||
* SELECT C_Payment_ID FROM C_Payment WHERE UPPER(DocumentNo) LIKE x OR ...
|
||||
*/
|
||||
private String getDirectAccessSQL (String text)
|
||||
{
|
||||
String m_columnName = getColumnName();
|
||||
|
||||
StringBuffer sql = new StringBuffer();
|
||||
m_tableName = m_columnName.substring(0, m_columnName.length()-3);
|
||||
m_keyColumnName = m_columnName;
|
||||
|
||||
if (m_columnName.equals("M_Product_ID"))
|
||||
{
|
||||
// Reset
|
||||
Env.setContext(Env.getCtx(), lookup.getWindowNo(), Env.TAB_INFO, "M_Product_ID", "0");
|
||||
Env.setContext(Env.getCtx(), lookup.getWindowNo(), Env.TAB_INFO, "M_AttributeSetInstance_ID", "0");
|
||||
Env.setContext(Env.getCtx(), lookup.getWindowNo(), Env.TAB_INFO, "M_Locator_ID", "0");
|
||||
|
||||
sql.append("SELECT M_Product_ID FROM M_Product WHERE (UPPER(Value) LIKE ")
|
||||
.append(DB.TO_STRING(text))
|
||||
.append(" OR UPPER(Name) LIKE ").append(DB.TO_STRING(text))
|
||||
.append(" OR UPC LIKE ").append(DB.TO_STRING(text)).append(")");
|
||||
}
|
||||
else if (m_columnName.equals("C_BPartner_ID"))
|
||||
{
|
||||
sql.append("SELECT C_BPartner_ID FROM C_BPartner WHERE (UPPER(Value) LIKE ")
|
||||
.append(DB.TO_STRING(text))
|
||||
.append(" OR UPPER(Name) LIKE ").append(DB.TO_STRING(text)).append(")");
|
||||
}
|
||||
else if (m_columnName.equals("C_Order_ID"))
|
||||
{
|
||||
sql.append("SELECT C_Order_ID FROM C_Order WHERE UPPER(DocumentNo) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
}
|
||||
else if (m_columnName.equals("C_Invoice_ID"))
|
||||
{
|
||||
sql.append("SELECT C_Invoice_ID FROM C_Invoice WHERE UPPER(DocumentNo) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
}
|
||||
else if (m_columnName.equals("M_InOut_ID"))
|
||||
{
|
||||
sql.append("SELECT M_InOut_ID FROM M_InOut WHERE UPPER(DocumentNo) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
}
|
||||
else if (m_columnName.equals("C_Payment_ID"))
|
||||
{
|
||||
sql.append("SELECT C_Payment_ID FROM C_Payment WHERE UPPER(DocumentNo) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
}
|
||||
else if (m_columnName.equals("GL_JournalBatch_ID"))
|
||||
{
|
||||
sql.append("SELECT GL_JournalBatch_ID FROM GL_JournalBatch WHERE UPPER(DocumentNo) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
}
|
||||
else if (m_columnName.equals("SalesRep_ID"))
|
||||
{
|
||||
sql.append("SELECT AD_User_ID FROM AD_User WHERE UPPER(Name) LIKE ")
|
||||
.append(DB.TO_STRING(text));
|
||||
|
||||
m_tableName = "AD_User";
|
||||
m_keyColumnName = "AD_User_ID";
|
||||
}
|
||||
|
||||
// Predefined
|
||||
|
||||
if (sql.length() > 0)
|
||||
{
|
||||
String wc = getWhereClause();
|
||||
|
||||
if (wc != null && wc.length() > 0)
|
||||
sql.append(" AND ").append(wc);
|
||||
|
||||
sql.append(" AND IsActive='Y'");
|
||||
// ***
|
||||
|
||||
if (log.isLoggable(Level.FINEST)) log.finest(m_columnName + " (predefined) " + sql.toString());
|
||||
|
||||
return MRole.getDefault().addAccessSQL(sql.toString(),
|
||||
m_tableName, MRole.SQL_NOTQUALIFIED, MRole.SQL_RO);
|
||||
}
|
||||
|
||||
// Check if it is a Table Reference
|
||||
|
||||
if (lookup != null && lookup instanceof MLookup)
|
||||
{
|
||||
int AD_Reference_ID = ((MLookup)lookup).getAD_Reference_Value_ID();
|
||||
|
||||
if (AD_Reference_ID != 0)
|
||||
{
|
||||
boolean isValueDisplayed = false;
|
||||
String query = "SELECT kc.ColumnName, dc.ColumnName, t.TableName, rt.IsValueDisplayed "
|
||||
+ "FROM AD_Ref_Table rt"
|
||||
+ " INNER JOIN AD_Column kc ON (rt.AD_Key=kc.AD_Column_ID)"
|
||||
+ " INNER JOIN AD_Column dc ON (rt.AD_Display=dc.AD_Column_ID)"
|
||||
+ " INNER JOIN AD_Table t ON (rt.AD_Table_ID=t.AD_Table_ID) "
|
||||
+ "WHERE rt.AD_Reference_ID=?";
|
||||
|
||||
String displayColumnName = null;
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(query, null);
|
||||
pstmt.setInt(1, AD_Reference_ID);
|
||||
rs = pstmt.executeQuery();
|
||||
|
||||
if (rs.next())
|
||||
{
|
||||
m_keyColumnName = rs.getString(1);
|
||||
displayColumnName = rs.getString(2);
|
||||
m_tableName = rs.getString(3);
|
||||
String t = rs.getString(4);
|
||||
isValueDisplayed = "Y".equalsIgnoreCase(t);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.SEVERE, query, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
}
|
||||
|
||||
|
||||
if (displayColumnName != null)
|
||||
{
|
||||
sql = new StringBuffer();
|
||||
sql.append("SELECT ").append(m_keyColumnName)
|
||||
.append(" FROM ").append(m_tableName)
|
||||
.append(" WHERE (UPPER(").append(displayColumnName)
|
||||
.append(") LIKE ").append(DB.TO_STRING(text));
|
||||
if (isValueDisplayed)
|
||||
{
|
||||
sql.append(" OR UPPER(").append("Value")
|
||||
.append(") LIKE ").append(DB.TO_STRING(text));
|
||||
}
|
||||
sql.append(")");
|
||||
sql.append(" AND IsActive='Y'");
|
||||
|
||||
String wc = getWhereClause();
|
||||
|
||||
if (wc != null && wc.length() > 0)
|
||||
sql.append(" AND ").append(wc);
|
||||
|
||||
// ***
|
||||
|
||||
if (log.isLoggable(Level.FINEST)) log.finest(m_columnName + " (Table) " + sql.toString());
|
||||
|
||||
return MRole.getDefault().addAccessSQL(sql.toString(),
|
||||
m_tableName, MRole.SQL_NOTQUALIFIED, MRole.SQL_RO);
|
||||
}
|
||||
} // Table Reference
|
||||
} // MLookup
|
||||
|
||||
/** Check Well Known Columns of Table - assumes TableDir **/
|
||||
|
||||
String query = "SELECT t.TableName, c.ColumnName "
|
||||
+ "FROM AD_Column c "
|
||||
+ " INNER JOIN AD_Table t ON (c.AD_Table_ID=t.AD_Table_ID AND t.IsView='N') "
|
||||
+ "WHERE (c.ColumnName IN ('DocumentNo', 'Value', 'Name') OR c.IsIdentifier='Y')"
|
||||
+ " AND c.AD_Reference_ID IN (10,14)"
|
||||
+ " AND EXISTS (SELECT * FROM AD_Column cc WHERE cc.AD_Table_ID=t.AD_Table_ID"
|
||||
+ " AND cc.IsKey='Y' AND cc.ColumnName=?)";
|
||||
|
||||
m_keyColumnName = m_columnName;
|
||||
sql = new StringBuffer();
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(query, null);
|
||||
pstmt.setString(1, m_keyColumnName);
|
||||
rs = pstmt.executeQuery();
|
||||
|
||||
while (rs.next())
|
||||
{
|
||||
if (sql.length() != 0)
|
||||
sql.append(" OR ");
|
||||
|
||||
m_tableName = rs.getString(1);
|
||||
sql.append("UPPER(").append(rs.getString(2)).append(") LIKE ").append(DB.TO_STRING(text));
|
||||
}
|
||||
}
|
||||
catch (SQLException ex)
|
||||
{
|
||||
log.log(Level.SEVERE, query, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
//
|
||||
if (sql.length() == 0)
|
||||
{
|
||||
log.log(Level.SEVERE, m_columnName + " (TableDir) - no standard/identifier columns");
|
||||
return "";
|
||||
}
|
||||
//
|
||||
StringBuffer retValue = new StringBuffer ("SELECT ")
|
||||
.append(m_columnName).append(" FROM ").append(m_tableName)
|
||||
.append(" WHERE ").append(sql)
|
||||
.append(" AND IsActive='Y'");
|
||||
|
||||
String wc = getWhereClause();
|
||||
|
||||
if (wc != null && wc.length() > 0)
|
||||
retValue.append(" AND ").append(wc);
|
||||
// ***
|
||||
if (log.isLoggable(Level.FINEST)) log.finest(m_columnName + " (TableDir) " + sql.toString());
|
||||
return MRole.getDefault().addAccessSQL(retValue.toString(),
|
||||
m_tableName, MRole.SQL_NOTQUALIFIED, MRole.SQL_RO);
|
||||
}
|
||||
|
||||
private String getWhereClause()
|
||||
{
|
||||
String whereClause = "";
|
||||
|
||||
if (lookup == null)
|
||||
return "";
|
||||
|
||||
String validation = lookup.getValidation();
|
||||
|
||||
if (validation == null)
|
||||
validation = "";
|
||||
|
||||
if (whereClause.length() == 0)
|
||||
whereClause = validation;
|
||||
else if (validation.length() > 0)
|
||||
whereClause += " AND " + validation;
|
||||
|
||||
if (whereClause.indexOf('@') != -1)
|
||||
{
|
||||
Properties ctx = lookup instanceof MLookup ? ((MLookup)lookup).getLookupInfo().ctx : Env.getCtx();
|
||||
String validated = Env.parseContext(ctx, lookup.getWindowNo(), whereClause, false);
|
||||
|
||||
if (validated.length() == 0)
|
||||
log.severe(getColumnName() + " - Cannot Parse=" + whereClause);
|
||||
else
|
||||
{
|
||||
if (log.isLoggable(Level.FINE))
|
||||
log.fine(getColumnName() + " - Parsed: " + validated);
|
||||
return validated;
|
||||
}
|
||||
}
|
||||
return whereClause;
|
||||
} // getWhereClause
|
||||
|
||||
|
||||
public String[] getEvents()
|
||||
{
|
||||
return LISTENER_EVENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTableEditor(boolean b) {
|
||||
super.setTableEditor(b);
|
||||
getComponent().setTableEditorMode(b);
|
||||
}
|
||||
|
||||
public Lookup getLookup() {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dynamicDisplay(Properties ctx) {
|
||||
if (lookup instanceof MLookup) {
|
||||
((MLookup) lookup).getLookupInfo().ctx = ctx;
|
||||
}
|
||||
super.dynamicDisplay(ctx);
|
||||
}
|
||||
|
||||
private class MyListModel extends ListModelList<ValueNamePair> implements ListSubModel<ValueNamePair> {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -1210525428410505409L;
|
||||
|
||||
@Override
|
||||
public ListModel<ValueNamePair> getSubModel(Object value, int nRows) {
|
||||
ListModelList<ValueNamePair> model = new ListModelList<>();
|
||||
if (value != null && !Util.isEmpty(value.toString(), true)) {
|
||||
String queryText = value.toString().trim();
|
||||
|
||||
if (m_tableName == null) // sets table name & key column
|
||||
getDirectAccessSQL("*");
|
||||
|
||||
final InfoPanel ip = InfoManager.create(lookup, gridField, m_tableName, m_keyColumnName, queryText, false, getWhereClause());
|
||||
if (ip != null && ip.loadedOK()) {
|
||||
int rowCount = ip.getRowCount();
|
||||
if (rowCount > 0) {
|
||||
List<String> added = new ArrayList<String>();
|
||||
for(int i = 0; i < rowCount; i++) {
|
||||
Integer key = ip.getRowKeyAt(i);
|
||||
if (key != null && key.intValue() > 0) {
|
||||
String name = getLookup().getDisplay(key);
|
||||
if (added.contains(name))
|
||||
continue;
|
||||
else
|
||||
added.add(name);
|
||||
ValueNamePair pair = new ValueNamePair(key.toString(), name);
|
||||
model.add(pair);
|
||||
if (added.size() == 50)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getComponent().getChosenbox().setSubListModel(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@ import org.adempiere.webui.editor.WAssignmentEditor;
|
|||
import org.adempiere.webui.editor.WBinaryEditor;
|
||||
import org.adempiere.webui.editor.WButtonEditor;
|
||||
import org.adempiere.webui.editor.WChartEditor;
|
||||
import org.adempiere.webui.editor.WChosenboxListEditor;
|
||||
import org.adempiere.webui.editor.WChosenboxSearchEditor;
|
||||
import org.adempiere.webui.editor.WDashboardContentEditor;
|
||||
import org.adempiere.webui.editor.WDateEditor;
|
||||
import org.adempiere.webui.editor.WDatetimeEditor;
|
||||
|
@ -209,6 +211,14 @@ public class DefaultEditorFactory implements IEditorFactory {
|
|||
{
|
||||
editor = new WGridTabMultiSelectionEditor(gridField, tableEditor);
|
||||
}
|
||||
else if (displayType == DisplayType.ChosenMultipleSelectionList || displayType == DisplayType.ChosenMultipleSelectionTable)
|
||||
{
|
||||
editor = new WChosenboxListEditor(gridField);
|
||||
}
|
||||
else if (displayType == DisplayType.ChosenMultipleSelectionSearch)
|
||||
{
|
||||
editor = new WChosenboxSearchEditor(gridField);
|
||||
}
|
||||
else
|
||||
{
|
||||
editor = new WUnknownEditor(gridField);
|
||||
|
|
|
@ -71,7 +71,6 @@ import org.compiere.model.AccessSqlParser.TableInfo;
|
|||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.GridFieldVO;
|
||||
import org.compiere.model.GridWindow;
|
||||
import org.compiere.model.Lookup;
|
||||
import org.compiere.model.MInfoColumn;
|
||||
import org.compiere.model.MInfoWindow;
|
||||
import org.compiere.model.MLookupFactory;
|
||||
|
@ -874,7 +873,8 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
if (! colSQL.toUpperCase().contains(" AS "))
|
||||
colSQL += " AS " + infoColumn.getColumnName();
|
||||
editorMap.put(colSQL, editor);
|
||||
ColumnInfo columnInfo = new ColumnInfo(infoColumn.get_Translation("Name"), colSQL, KeyNamePair.class, (String)null, infoColumn.isReadOnly() || haveNotProcess);
|
||||
Class<?> colClass = columnName.endsWith("_ID") ? KeyNamePair.class : String.class;
|
||||
ColumnInfo columnInfo = new ColumnInfo(infoColumn.get_Translation("Name"), colSQL, colClass, (String)null, infoColumn.isReadOnly() || haveNotProcess);
|
||||
return columnInfo;
|
||||
}
|
||||
|
||||
|
@ -947,6 +947,32 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
builder.append(checkAND.isChecked() ? " AND " : " OR ");
|
||||
}
|
||||
|
||||
if (mInfoColumn.getAD_Reference_ID() == DisplayType.ChosenMultipleSelectionList)
|
||||
{
|
||||
String pString = editor.getValue().toString();
|
||||
String column = columnName;
|
||||
if (column.indexOf(".") > 0)
|
||||
column = column.substring(column.indexOf(".")+1);
|
||||
int cnt = DB.getSQLValueEx(null, "SELECT Count(*) From AD_Column WHERE IsActive='Y' AND AD_Client_ID=0 AND Upper(ColumnName)=? AND AD_Reference_ID=?", column.toUpperCase(), DisplayType.ChosenMultipleSelectionList);
|
||||
if (cnt > 0)
|
||||
builder.append(DB.intersectClauseForCSV(columnName, pString));
|
||||
else
|
||||
builder.append(DB.inClauseForCSV(columnName, pString));
|
||||
}
|
||||
else if (mInfoColumn.getAD_Reference_ID() == DisplayType.ChosenMultipleSelectionTable || mInfoColumn.getAD_Reference_ID() == DisplayType.ChosenMultipleSelectionSearch)
|
||||
{
|
||||
String pString = editor.getValue().toString();
|
||||
if (columnName.endsWith("_ID"))
|
||||
{
|
||||
builder.append(DB.inClauseForCSV(columnName, pString));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append(DB.intersectClauseForCSV(columnName, pString));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String columnClause = null;
|
||||
if (mInfoColumn.getQueryFunction() != null && mInfoColumn.getQueryFunction().trim().length() > 0) {
|
||||
String function = mInfoColumn.getQueryFunction();
|
||||
|
@ -976,6 +1002,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0 && !checkAND.isChecked()) {
|
||||
builder.append(" ) ");
|
||||
}
|
||||
|
@ -1070,6 +1097,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
|||
if (mInfoColumn == null || mInfoColumn.getSelectClause().equals("0")) {
|
||||
continue;
|
||||
}
|
||||
if (mInfoColumn.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionList || mInfoColumn.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionSearch
|
||||
|| mInfoColumn.getAD_Reference_ID()==DisplayType.ChosenMultipleSelectionTable) {
|
||||
continue;
|
||||
}
|
||||
Object value = editor.getValue();
|
||||
parameterIndex++;
|
||||
prevParameterValues.add(value);
|
||||
|
|
|
@ -651,6 +651,14 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
else
|
||||
{
|
||||
value = rs.getString(colIndex);
|
||||
if (! rs.wasNull()) {
|
||||
WEditor editor = editorMap.get(p_layout[col].getColSQL());
|
||||
if (editor != null && editor.getGridField() != null && editor.getGridField().isLookup())
|
||||
{
|
||||
editor.setValue(value);
|
||||
value = editor.getDisplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
data.add(value);
|
||||
}
|
||||
|
@ -2532,6 +2540,10 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
|||
return contentPanel.getFirstRowKey();
|
||||
}
|
||||
|
||||
public Integer getRowKeyAt(int row) {
|
||||
return contentPanel.getRowKeyAt(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cacheStart
|
||||
*/
|
||||
|
|
|
@ -1701,6 +1701,15 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
}
|
||||
m_query.addRestriction(getSubCategoryWhereClause(field, ((Integer) parsedValue).intValue()), and, openBrackets);
|
||||
}
|
||||
else if ((field.getDisplayType()==DisplayType.ChosenMultipleSelectionList||field.getDisplayType()==DisplayType.ChosenMultipleSelectionSearch||field.getDisplayType()==DisplayType.ChosenMultipleSelectionTable) &&
|
||||
(MQuery.OPERATORS[MQuery.EQUAL_INDEX].getValue().equals(Operator) || MQuery.OPERATORS[MQuery.NOT_EQUAL_INDEX].getValue().equals(Operator)))
|
||||
{
|
||||
String clause = DB.intersectClauseForCSV(ColumnSQL, parsedValue.toString());
|
||||
if (MQuery.OPERATORS[MQuery.EQUAL_INDEX].getValue().equals(Operator))
|
||||
m_query.addRestriction(clause, and, openBrackets);
|
||||
else
|
||||
m_query.addRestriction("NOT (" + clause + ")", and, openBrackets);
|
||||
}
|
||||
else
|
||||
m_query.addRestriction(ColumnSQL, Operator, parsedValue,
|
||||
infoName, infoDisplay, and, openBrackets);
|
||||
|
@ -1849,6 +1858,13 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
continue;
|
||||
}
|
||||
|
||||
if (field.getDisplayType()==DisplayType.ChosenMultipleSelectionList||field.getDisplayType()==DisplayType.ChosenMultipleSelectionSearch||field.getDisplayType()==DisplayType.ChosenMultipleSelectionTable)
|
||||
{
|
||||
String clause = DB.intersectClauseForCSV(ColumnSQL.toString(), value.toString());
|
||||
m_query.addRestriction(clause);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Be more permissive for String columns
|
||||
if (isSearchLike(field))
|
||||
|
|
|
@ -0,0 +1,899 @@
|
|||
/******************************************************************************
|
||||
* Project: Trek Global ERP *
|
||||
*
|
||||
* Chosenbox.java
|
||||
|
||||
Purpose:
|
||||
|
||||
Description:
|
||||
|
||||
History:
|
||||
Tue Nov 16 15:15:52 TST 2011, Created by benbai
|
||||
|
||||
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
|
||||
|
||||
{{IS_RIGHT
|
||||
This program is distributed under LGPL Version 3.0 in the hope that
|
||||
it will be useful, but WITHOUT ANY WARRANTY.
|
||||
}}IS_RIGHT
|
||||
*/
|
||||
package org.zkoss.addon.chosenbox;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.zkoss.lang.Objects;
|
||||
import org.zkoss.xel.VariableResolver;
|
||||
import org.zkoss.zk.au.out.AuSetAttribute;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.HtmlBasedComponent;
|
||||
import org.zkoss.zk.ui.UiException;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
import org.zkoss.zk.ui.event.Events;
|
||||
import org.zkoss.zk.ui.event.InputEvent;
|
||||
import org.zkoss.zk.ui.event.OpenEvent;
|
||||
import org.zkoss.zk.ui.event.SelectEvent;
|
||||
import org.zkoss.zk.ui.util.Clients;
|
||||
import org.zkoss.zk.ui.util.ForEachStatus;
|
||||
import org.zkoss.zk.ui.util.Template;
|
||||
import org.zkoss.zul.ItemRenderer;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.ListModel;
|
||||
import org.zkoss.zul.ListModelList;
|
||||
import org.zkoss.zul.ListSubModel;
|
||||
import org.zkoss.zul.event.ListDataEvent;
|
||||
import org.zkoss.zul.event.ListDataListener;
|
||||
|
||||
/**
|
||||
* A ZK component like JQuery Chosen.
|
||||
* <p>Default {@link #getZclass}: z-chosenbox.
|
||||
* It does not create child widgets for each data, so the memory usage is much
|
||||
* lower at the server.
|
||||
* @author benbai
|
||||
*
|
||||
*/
|
||||
public class Chosenbox<T> extends HtmlBasedComponent {
|
||||
private static final String CHOSENBOX_PREPARE_DATA = "chosenbox.prepareData";
|
||||
/**
|
||||
* generated serial id
|
||||
*/
|
||||
private static final long serialVersionUID = 4501010016457525407L;
|
||||
private List<Integer> _selIdxs = new ArrayList<>();
|
||||
private String _name, _value = "";
|
||||
private boolean _disabled;
|
||||
private int _jsel = -1;
|
||||
private int _tabindex;
|
||||
private boolean _open;
|
||||
private boolean _creatable;
|
||||
private String _emptyMessage;
|
||||
private String _noResultsText;
|
||||
private String _createMessage;
|
||||
private String _separator;
|
||||
private transient ListModelList<T> _model;
|
||||
private transient ListModel<T> _subListModel;
|
||||
private transient ListDataListener _dataListener;
|
||||
private transient EventListener<InputEvent> _eventListener;
|
||||
private transient ItemRenderer<T> _renderer;
|
||||
private transient boolean _childable;
|
||||
private transient String[] _options;
|
||||
private transient String[] _chgSel;
|
||||
private long _onSelectTimestamp;
|
||||
private long _onOkTimestamp;
|
||||
static {
|
||||
addClientEvent(Chosenbox.class, Events.ON_SELECT, CE_DUPLICATE_IGNORE | CE_IMPORTANT);
|
||||
addClientEvent(Chosenbox.class, Events.ON_FOCUS, CE_DUPLICATE_IGNORE);
|
||||
addClientEvent(Chosenbox.class, Events.ON_BLUR, CE_DUPLICATE_IGNORE);
|
||||
addClientEvent(Chosenbox.class, Events.ON_OPEN, CE_IMPORTANT);
|
||||
addClientEvent(Chosenbox.class, "onSearching", CE_DUPLICATE_IGNORE | CE_IMPORTANT);
|
||||
addClientEvent(Chosenbox.class, "onSearch", CE_DUPLICATE_IGNORE | CE_IMPORTANT);
|
||||
addClientEvent(Chosenbox.class, Events.ON_OK, CE_DUPLICATE_IGNORE | CE_IMPORTANT);
|
||||
}
|
||||
|
||||
public Chosenbox() {
|
||||
addEventListener("onOkTimer", e -> {
|
||||
onOkTimer();
|
||||
});
|
||||
}
|
||||
|
||||
private void onOkTimer() {
|
||||
if (_onSelectTimestamp==0 || _onOkTimestamp==0) {
|
||||
postOnOk();
|
||||
} else {
|
||||
long diff = _onSelectTimestamp - _onOkTimestamp;
|
||||
_onSelectTimestamp = _onOkTimestamp = 0;
|
||||
if (diff < 0)
|
||||
diff = diff * -1l;
|
||||
if (diff > 500)
|
||||
postOnOk();
|
||||
}
|
||||
}
|
||||
|
||||
private void postOnOk() {
|
||||
Component p = getParent();
|
||||
while (p != null) {
|
||||
Iterable<EventListener<? extends Event>> iterable = p.getEventListeners(Events.ON_OK);
|
||||
if (iterable.iterator().hasNext()) {
|
||||
Events.postEvent(Events.ON_OK, p, null);
|
||||
break;
|
||||
} else {
|
||||
p = p.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getZclass() {
|
||||
return _zclass == null ? "z-chosenbox" : _zclass;
|
||||
}
|
||||
|
||||
public void setOpen(boolean open) {
|
||||
if (_open != open) {
|
||||
_open = open;
|
||||
smartUpdate("open", _open);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return _open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tab order of the input node of this component.
|
||||
* <p>
|
||||
* Default: 0 (means the same as browser's default).
|
||||
*/
|
||||
public int getTabindex() {
|
||||
return _tabindex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tab order of the input node of this component.
|
||||
*/
|
||||
public void setTabindex(int tabindex) throws WrongValueException {
|
||||
if (_tabindex != tabindex) {
|
||||
_tabindex = tabindex;
|
||||
smartUpdate("tabindex", tabindex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether it is disabled.
|
||||
* <p>
|
||||
* Default: false.
|
||||
*/
|
||||
public boolean isDisabled() {
|
||||
return _disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether it is disabled.
|
||||
*/
|
||||
public void setDisabled(boolean disabled) {
|
||||
if (_disabled != disabled) {
|
||||
_disabled = disabled;
|
||||
smartUpdate("disabled", _disabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this component.
|
||||
* <p>
|
||||
* Default: null.
|
||||
* <p>
|
||||
* The name is used only to work with "legacy" Web application that handles
|
||||
* user's request by servlets. It works only with HTTP/HTML-based browsers.
|
||||
* It doesn't work with other kind of clients.
|
||||
* <p>
|
||||
* Don't use this method if your application is purely based on ZK's
|
||||
* event-driven model.
|
||||
*/
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the input element of this component.
|
||||
* <p>
|
||||
* The name is used only to work with "legacy" Web application that handles
|
||||
* user's request by servlets. It works only with HTTP/HTML-based browsers.
|
||||
* It doesn't work with other kind of clients.
|
||||
* <p>
|
||||
* Don't use this method if your application is purely based on ZK's
|
||||
* event-driven model.
|
||||
*
|
||||
* @param name
|
||||
* the name of this component.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (name != null && name.length() == 0)
|
||||
name = null;
|
||||
if (!Objects.equals(_name, name)) {
|
||||
_name = name;
|
||||
smartUpdate("name", name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the emptyMessage of the input of this component.
|
||||
* <p>
|
||||
* Default: null.
|
||||
* <p>
|
||||
* The emptyMessage will be displayed in input if nothing selected and not focused.
|
||||
* @return String
|
||||
*/
|
||||
public String getEmptyMessage() {
|
||||
return _emptyMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the emptyMessage of the input of this component.
|
||||
* <p>
|
||||
* The emptyMessage will be displayed in input if nothing selected and not focused.
|
||||
* @param String emptyMessage
|
||||
* the emptyMessage of the input of this component.
|
||||
*/
|
||||
public void setEmptyMessage(String emptyMessage) {
|
||||
if (emptyMessage != null && emptyMessage.length() == 0)
|
||||
emptyMessage = null;
|
||||
if (!Objects.equals(_emptyMessage, emptyMessage)) {
|
||||
_emptyMessage = emptyMessage;
|
||||
smartUpdate("emptyMessage", getEmptyMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the no-result text of this component.
|
||||
* <p>
|
||||
* Default: null.
|
||||
* <p>
|
||||
* The no-result text will be displayed in popup if nothing match to the input value and can not create either,
|
||||
* the syntax "{0}" will be replaced with the input value at client side.
|
||||
* @return String
|
||||
*/
|
||||
public String getNoResultsText() {
|
||||
return _noResultsText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the no-result text of this component.
|
||||
* <p>
|
||||
* The no-result text will be displayed in popup if nothing match to the input value and can not create either,
|
||||
* the syntax "{0}" will be replaced with the input value at client side.
|
||||
* @param String noResultsText
|
||||
* the no-result text of this component.
|
||||
*/
|
||||
public void setNoResultsText(String noResultsText) {
|
||||
if (noResultsText != null && noResultsText.length() == 0)
|
||||
noResultsText = null;
|
||||
if (!Objects.equals(_noResultsText, noResultsText)) {
|
||||
_noResultsText = noResultsText;
|
||||
smartUpdate("noResultsText", getNoResultsText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the create message of this component.
|
||||
* <p>
|
||||
* Default: null.
|
||||
* <p>
|
||||
* The create message will be displayed in popup if nothing match to the input value but can create as new label,
|
||||
* the syntax "{0}" will be replaced with the input value at client side.
|
||||
* @return String
|
||||
*/
|
||||
public String getCreateMessage() {
|
||||
return _createMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the create message of this component.
|
||||
* <p>
|
||||
* The create message will be displayed in popup if nothing match to the input value but can create as new label,
|
||||
* the syntax "{0}" will be replaced with the input value at client side.
|
||||
* @param String createMessage
|
||||
* the create message of this component.
|
||||
*/
|
||||
public void setCreateMessage(String createMessage) {
|
||||
if (createMessage != null && createMessage.length() == 0)
|
||||
createMessage = null;
|
||||
if (!Objects.equals(_createMessage, createMessage)) {
|
||||
_createMessage = createMessage;
|
||||
smartUpdate("createMessage", getCreateMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the separate chars of this component.
|
||||
* <p>
|
||||
* Support: 0-9, A-Z (case insensitive), and ,.;'[]/\-=
|
||||
* <p>
|
||||
* Default: null.
|
||||
* <p>
|
||||
* The separate chars will work as 'Enter' key,
|
||||
* it will not considered as input value but send onSerch or onSearching while key up.
|
||||
* @return String
|
||||
*/
|
||||
public String getSeparator() {
|
||||
return _separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the separate chars of this component.
|
||||
* <p>
|
||||
* Support: 0-9, A-Z (case insensitive), and ,.;'[]/\-=
|
||||
* <p>
|
||||
* The separate chars will work as 'Enter' key,
|
||||
* it will not considered as input value but send onSerch or onSelect while key up.
|
||||
* @param String createMessage
|
||||
* the create message of this component.
|
||||
*/
|
||||
public void setSeparator(String separator) {
|
||||
if (separator != null && separator.length() == 0)
|
||||
separator = null;
|
||||
if (!Objects.equals(_separator, separator)) {
|
||||
_separator = separator;
|
||||
smartUpdate("separator", getSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected objects.
|
||||
* @return Set
|
||||
*/
|
||||
public LinkedHashSet<T> getSelectedObjects () {
|
||||
final LinkedHashSet<T> objects = new LinkedHashSet<>();
|
||||
ListModel<T> model = this.getModel();
|
||||
if (model != null) {
|
||||
for (int i = 0; i < _selIdxs.size(); i ++) {
|
||||
objects.add(model.getElementAt(_selIdxs.get(i)));
|
||||
}
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected objects.
|
||||
* It will clear selection first.
|
||||
* @param List objects
|
||||
* the objects to select.
|
||||
*/
|
||||
public void setSelectedObjects (Set<T> objects) {
|
||||
// do nothing if no model
|
||||
if (getModel() != null) {
|
||||
_selIdxs.clear();
|
||||
ListModel<T> lm = getModel();
|
||||
boolean found = false;
|
||||
for (T object : objects) {
|
||||
for (int i = 0; i < lm.getSize(); i++) {
|
||||
if (lm.getElementAt(i).equals(object)) {
|
||||
if (_jsel == -1 || _jsel > i)
|
||||
_jsel = i;
|
||||
found = true;
|
||||
_selIdxs.add(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (Logger.getLogger(getClass().getName()).isLoggable(Level.INFO))
|
||||
Logger.getLogger(getClass().getName()).info("No such item: " + object);
|
||||
}
|
||||
found = false;
|
||||
}
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the selected item (-1 if no one is selected).
|
||||
* @return int
|
||||
*/
|
||||
public int getSelectedIndex() {
|
||||
return _jsel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the index of the selected item (-1 if no one is selected).
|
||||
* It will clear selection first.
|
||||
* @param int index
|
||||
* the index to select.
|
||||
*/
|
||||
public void setSelectedIndex(int jsel) {
|
||||
if (jsel <= -1)
|
||||
jsel = -1;
|
||||
if (jsel < 0) { // unselect all
|
||||
clearSelection();
|
||||
} else if (jsel != _jsel || _selIdxs.size() > 1) {
|
||||
if (_selIdxs.size() > 1 && jsel == _jsel) {
|
||||
// clear client side old value
|
||||
smartUpdate("selectedIndex", -1);
|
||||
}
|
||||
// check size
|
||||
if (getModel() != null && jsel >= getModel().getSize()) {
|
||||
throw new UiException("Out of bound: " + jsel + " while size="
|
||||
+ getModel().getSize());
|
||||
}
|
||||
_selIdxs.clear();
|
||||
_jsel = jsel;
|
||||
_selIdxs.add(jsel);
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether can create new item.
|
||||
* <p>
|
||||
* Default: false.
|
||||
* <p>
|
||||
* true: will show create message while value of input not exists.
|
||||
* <p>
|
||||
* false: will show no result message while value of input not exists.
|
||||
*/
|
||||
public boolean isCreatable() {
|
||||
return _creatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether can create new item.
|
||||
* <p>
|
||||
* Default: false.
|
||||
* <p>
|
||||
* true: will show create message while value of input not exists.
|
||||
* <p>
|
||||
* false: will show no-result text while value of input not exists.
|
||||
*
|
||||
* @param creatable
|
||||
* the boolean value.
|
||||
*/
|
||||
public void setCreatable(boolean creatable) {
|
||||
if (_creatable != creatable) {
|
||||
_creatable = creatable;
|
||||
smartUpdate("creatable", _creatable);
|
||||
}
|
||||
}
|
||||
|
||||
public ItemRenderer<T> getRealRenderer() {
|
||||
final ItemRenderer<T> renderer = getItemRenderer();
|
||||
return renderer != null ? renderer : _defRend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the renderer to render each item, or null if the default renderer
|
||||
* is used.
|
||||
*/
|
||||
public ItemRenderer<T> getItemRenderer() {
|
||||
return _renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model associated with this chosenbox, or null if this
|
||||
* chosenbox is not associated with any list data model.
|
||||
*/
|
||||
public ListModel<T> getModel() {
|
||||
return _model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list model associated with this chosenbox. If a non-null model
|
||||
* is assigned, no matter whether it is the same as the previous, it will
|
||||
* always cause re-render.
|
||||
*
|
||||
* @param model
|
||||
* the list model to associate, or null to dis-associate any
|
||||
* previous model.
|
||||
* @exception UiException
|
||||
* if failed to initialize with the model
|
||||
*/
|
||||
public void setModel(ListModelList<T> model) {
|
||||
if (model != null) {
|
||||
if (_model != model) {
|
||||
// fix selected index
|
||||
if (getSelectedIndex() >= model.getSize())
|
||||
setSelectedIndex(model.getSize()-1);
|
||||
if (_model != null) {
|
||||
_model.removeListDataListener(_dataListener);
|
||||
}
|
||||
_model = model;
|
||||
initDataListener();
|
||||
}
|
||||
} else if (_model != null) {
|
||||
_model.removeListDataListener(_dataListener);
|
||||
if (_model instanceof ListSubModel)
|
||||
removeEventListener("onSearching", _eventListener);
|
||||
_model = null;
|
||||
}
|
||||
fixIndexs(true, null);
|
||||
smartUpdate("renderByServer", _model instanceof ListSubModel);
|
||||
updateItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all selected objects.
|
||||
*/
|
||||
public void clearSelection() {
|
||||
_selIdxs.clear();
|
||||
_jsel = -1;
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item into selection.
|
||||
* @param o
|
||||
* the object to add.
|
||||
*/
|
||||
public void addItemToSelection(Object o) {
|
||||
// do nothing if no model
|
||||
if (getModel() != null) {
|
||||
ListModel<T> lm = getModel();
|
||||
for (int i = 0;i < lm.getSize();i ++) {
|
||||
if (lm.getElementAt(i).equals(o)) {
|
||||
_selIdxs.add(i);
|
||||
if (i < _jsel)
|
||||
_jsel = i;
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from selection.
|
||||
* @param o
|
||||
* the object to remove.
|
||||
*/
|
||||
public void removeItemFromSelection(Object o) {
|
||||
// do nothing if no model
|
||||
if (getModel() != null) {
|
||||
ListModel<T> lm = getModel();
|
||||
for (int i = 0;i < lm.getSize();i ++) {
|
||||
if (lm.getElementAt(i).equals(o)) {
|
||||
int cur = -1, min = -1;
|
||||
for (int j = 0; j < _selIdxs.size(); j++) {
|
||||
if (i == _selIdxs.get(j).intValue()) {
|
||||
cur = j;
|
||||
} else if (min == -1 || _selIdxs.get(j).intValue() < min) {
|
||||
min = _selIdxs.get(j).intValue();
|
||||
}
|
||||
}
|
||||
if (cur != -1) {
|
||||
_jsel = min;
|
||||
_selIdxs.remove(cur);
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getChgSel() {
|
||||
prepareItems(null, true, _model);
|
||||
if (_options != null) {
|
||||
String [] chgSel = _options;
|
||||
_options = null;
|
||||
return chgSel;
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
protected boolean isChildable() {
|
||||
return _childable;
|
||||
}
|
||||
|
||||
private void prepareData() {
|
||||
if (getAttribute(CHOSENBOX_PREPARE_DATA) != null)
|
||||
return;
|
||||
|
||||
if (_selIdxs.size() > 0)
|
||||
_chgSel = getChgSel();
|
||||
|
||||
if (!(_model instanceof ListSubModel))
|
||||
prepareItems(null, false, _model);
|
||||
|
||||
setAttribute(CHOSENBOX_PREPARE_DATA, Boolean.TRUE);
|
||||
}
|
||||
|
||||
// fix selected indexes while model changed or replaced
|
||||
private void fixIndexs(boolean modelReplaced, ListDataEvent event) {
|
||||
// model instance is changed
|
||||
if (modelReplaced) {
|
||||
if (_model == null) {
|
||||
clearSelection();
|
||||
} else {
|
||||
// remove the out of range indexes
|
||||
Iterator<Integer>it = _selIdxs.iterator();
|
||||
while (it.hasNext()) {
|
||||
if (it.next() >= _model.getSize()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int pos0 = event.getIndex0();
|
||||
int pos1 = event.getIndex1();
|
||||
int amount = pos1 - pos0 + 1;
|
||||
switch (event.getType()) {
|
||||
case ListDataEvent.INTERVAL_ADDED:
|
||||
for (int i = 0; i < _selIdxs.size(); i++) {
|
||||
if (_selIdxs.get(i) >= pos0)
|
||||
_selIdxs.set(i, _selIdxs.get(i) + amount);
|
||||
}
|
||||
break;
|
||||
case ListDataEvent.INTERVAL_REMOVED:
|
||||
for(ListIterator<Integer> lit = _selIdxs.listIterator(); lit.hasNext();) {
|
||||
Integer i = lit.next();
|
||||
if (i > pos1)
|
||||
lit.set(i - amount);
|
||||
else if (i >= pos0)
|
||||
lit.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* prepare the list content or selected items to render,
|
||||
* @param prefix
|
||||
* Only add the item starts with it if it is not null.
|
||||
* @param excludeUnselected
|
||||
* Only add selected item, with select order.
|
||||
* @param model
|
||||
* the model to render.
|
||||
*/
|
||||
private void prepareItems(String prefix, boolean excludeUnselected, ListModel<T> model) {
|
||||
if (model != null) {
|
||||
List<String> optList = new ArrayList<String>();
|
||||
final boolean old = _childable;
|
||||
try {
|
||||
_childable = true;
|
||||
final ItemRenderer<T> renderer = getRealRenderer();
|
||||
// order by _selIdxs content if only prepare selected items
|
||||
if (excludeUnselected) {
|
||||
for (int i = 0; i < _selIdxs.size(); i++) {
|
||||
String s = renderer.render(this, model.getElementAt(_selIdxs.get(i)), _selIdxs.get(i));
|
||||
if (prefix == null || s.toLowerCase().startsWith(prefix.toLowerCase()))
|
||||
optList.add(s);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < model.getSize(); i++) {
|
||||
String s = renderer.render(this, model.getElementAt(i), i);
|
||||
if (prefix == null || s.toLowerCase().startsWith(prefix.toLowerCase()))
|
||||
optList.add(s);
|
||||
}
|
||||
}
|
||||
if (optList.size() > 0)
|
||||
_options = optList.toArray(new String[0]);
|
||||
} catch (Exception e) {
|
||||
throw UiException.Aide.wrap(e);
|
||||
} finally {
|
||||
//clear possible children created in renderer
|
||||
_childable = old;
|
||||
getChildren().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItems() {
|
||||
prepareItems(null, false, _model);
|
||||
if (_options != null) {
|
||||
smartUpdate("items", _options);
|
||||
_options = null; //purge the data
|
||||
}
|
||||
smartUpdate("chgSel", getChgSel());
|
||||
}
|
||||
|
||||
private void updateListContent(String prefix, ListModel<T> subModel) {
|
||||
if (!(_model instanceof ListSubModel))
|
||||
prepareItems(null, false, subModel);
|
||||
else
|
||||
prepareItems(prefix, false, subModel);
|
||||
if (_options != null) {
|
||||
smartUpdate("listContent", _options);
|
||||
_options = null; //purge the data
|
||||
} else
|
||||
smartUpdate("listContent", new String[0]);
|
||||
}
|
||||
|
||||
private void initDataListener() {
|
||||
if (_dataListener == null)
|
||||
_dataListener = new ListDataListener() {
|
||||
public void onChange(ListDataEvent event) {
|
||||
fixIndexs(false, event);
|
||||
updateItems();
|
||||
}
|
||||
};
|
||||
if (_eventListener == null)
|
||||
_eventListener = new EventListener<InputEvent>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onEvent(InputEvent event) throws Exception {
|
||||
if (getModel() instanceof ListSubModel) {
|
||||
updateListContent(null, ((ListSubModel<T>)_model).getSubModel(event.getValue(), _model.getSize()));
|
||||
}
|
||||
}
|
||||
};
|
||||
_model.addListDataListener(_dataListener);
|
||||
|
||||
if (_model instanceof ListSubModel)
|
||||
addEventListener("onSearching", _eventListener);
|
||||
}
|
||||
|
||||
private Integer getIndexFromValue(String value, boolean checkSubList) {
|
||||
for (int i = 0; i < _model.getSize(); i++) {
|
||||
if (value.equals(_model.getElementAt(i).toString()))
|
||||
return Integer.valueOf(i);
|
||||
}
|
||||
if (checkSubList && _subListModel != null) {
|
||||
for (int i = 0; i < _subListModel.getSize(); i++) {
|
||||
if (value.equals(_subListModel.getElementAt(i).toString())) {
|
||||
_model.add(_subListModel.getElementAt(i));
|
||||
return Integer.valueOf(_model.getSize()-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new UiException("No such item: " + value);
|
||||
}
|
||||
|
||||
// -- ComponentCtrl --//
|
||||
public void invalidate() {
|
||||
prepareData();
|
||||
super.invalidate();
|
||||
}
|
||||
|
||||
protected void renderProperties(org.zkoss.zk.ui.sys.ContentRenderer renderer)
|
||||
throws IOException {
|
||||
super.renderProperties(renderer);
|
||||
prepareData();
|
||||
removeAttribute(CHOSENBOX_PREPARE_DATA);
|
||||
if (_options != null) {
|
||||
render(renderer, "items", _options);
|
||||
_options = null; //purge the data
|
||||
} else {
|
||||
render(renderer, "items", new String[0]);
|
||||
}
|
||||
if (_chgSel != null) {
|
||||
render(renderer, "chgSel", _chgSel);
|
||||
_chgSel = null; //purge the data
|
||||
} else {
|
||||
render(renderer, "chgSel", new String[0]);
|
||||
}
|
||||
|
||||
render(renderer, "name", _name);
|
||||
render(renderer, "disabled", isDisabled());
|
||||
if (_tabindex != 0)
|
||||
renderer.render("tabindex", _tabindex);
|
||||
|
||||
render(renderer, "emptyMessage", getEmptyMessage());
|
||||
render(renderer, "noResultsText", getNoResultsText());
|
||||
render(renderer, "separator", getSeparator());
|
||||
render(renderer, "createMessage", getCreateMessage());
|
||||
renderer.render("selectedIndex", _jsel);
|
||||
renderer.render("creatable", _creatable);
|
||||
renderer.render("renderByServer", _model instanceof ListSubModel);
|
||||
render(renderer, "open", _open);
|
||||
|
||||
//maintain selected items for listsubmodel/renderbyserver
|
||||
if (_model instanceof ListSubModel && _selIdxs.size() > 0) {
|
||||
prepareItems(null, true, _model);
|
||||
if (_options != null && _options.length > 0) {
|
||||
response("listContent", new AuSetAttribute(this, "listContent", _options));
|
||||
response("chgSel", new AuSetAttribute(this, "chgSel", _options));
|
||||
_options = null; //purge the data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void service(org.zkoss.zk.au.AuRequest request, boolean everError) {
|
||||
final String cmd = request.getCommand();
|
||||
if (cmd.equals(Events.ON_SELECT)) {
|
||||
List<?> selItems = (List<?>)request.getData().get("");
|
||||
// clear at first
|
||||
_selIdxs.clear();
|
||||
_jsel = -1;
|
||||
|
||||
for (int i = 0; i < selItems.size(); i++) {
|
||||
int idx = getIndexFromValue(selItems.get(i).toString(), true);
|
||||
_selIdxs.add(idx);
|
||||
if (idx < _jsel || _jsel == -1)
|
||||
_jsel = idx;
|
||||
}
|
||||
final Integer index = getSelectedIndex();
|
||||
final Set<T> objects = getSelectedObjects();
|
||||
Events.postEvent(new SelectEvent<Component, T>(Events.ON_SELECT, this, null, null, null,
|
||||
objects, null, null, null, index, 0));
|
||||
_onSelectTimestamp = System.currentTimeMillis();
|
||||
} else if (cmd.equals(Events.ON_OPEN)) {
|
||||
_open = (Boolean)request.getData().get("open");
|
||||
Events.postEvent(OpenEvent.getOpenEvent(request));
|
||||
} else if (cmd.equals("onSearch")) {
|
||||
Events.postEvent(new Event("onSearch", this, ((List<?>)request.getData().get("")).get(0).toString()));
|
||||
} else if (cmd.equals("onSearching")) {
|
||||
Object data = ((List<?>)request.getData().get("")).get(0);
|
||||
Events.postEvent(new InputEvent(cmd, this, (String)data, _value));
|
||||
_value = (String)data;
|
||||
} else if (cmd.equals(Events.ON_OK)) {
|
||||
_onOkTimestamp = System.currentTimeMillis();
|
||||
Clients.evalJavaScript("setTimeout(function(){zAu.send(new zk.Event(zk.Widget.$('#"
|
||||
+ getUuid() + "'), 'onOkTimer', null));}, 100);");
|
||||
} else if (cmd.equals("onOkTimer")) {
|
||||
Events.postEvent("onOkTimer", this, null);
|
||||
}
|
||||
}
|
||||
|
||||
public ListModel<T> getSubListModel() {
|
||||
return _subListModel;
|
||||
}
|
||||
|
||||
public void setSubListModel(ListModel<T> _subListModel) {
|
||||
this._subListModel = _subListModel;
|
||||
}
|
||||
|
||||
private final ItemRenderer<T> _defRend = new ItemRenderer<T>() {
|
||||
public String render(final Component owner, final T data, final int index) {
|
||||
final Chosenbox<?> self = (Chosenbox<?>) owner;
|
||||
final Template tm = self.getTemplate("model");
|
||||
if (tm == null)
|
||||
return Objects.toString(data);
|
||||
else {
|
||||
final Component[] items = tm.create(owner, null,
|
||||
new VariableResolver() {
|
||||
public Object resolveVariable(String name) {
|
||||
if ("each".equals(name)) {
|
||||
return data;
|
||||
} else if ("forEachStatus".equals(name)) {
|
||||
return new ForEachStatus() {
|
||||
public ForEachStatus getPrevious() {
|
||||
return null;
|
||||
}
|
||||
public Object getEach() {
|
||||
return data;
|
||||
}
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
public Integer getBegin() {
|
||||
return 0;
|
||||
}
|
||||
public Integer getEnd() {
|
||||
return ((Chosenbox<?>)owner).getModel().getSize();
|
||||
}
|
||||
public boolean isFirst() {
|
||||
return index == 0;
|
||||
}
|
||||
public boolean isLast() {
|
||||
return (index+1) == ((Chosenbox<?>)owner).getModel().getSize();
|
||||
}
|
||||
public int getCount() {
|
||||
return index+1;
|
||||
}
|
||||
public Object getCurrent() {
|
||||
return data;
|
||||
}
|
||||
public Integer getStep() {
|
||||
return Integer.valueOf(1);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
if (items.length != 1)
|
||||
throw new UiException(
|
||||
"The model template must have exactly one item, not "
|
||||
+ items.length);
|
||||
if (!(items[0] instanceof Label))
|
||||
throw new UiException(
|
||||
"The model template can only support Label component, not "
|
||||
+ items[0]);
|
||||
items[0].detach(); //remove the label from owner
|
||||
return ((Label) items[0]).getValue();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* Chosenbox.java
|
||||
|
||||
Purpose:
|
||||
|
||||
Description:
|
||||
|
||||
History:
|
||||
Tue Nov 16 15:15:52 TST 2011, Created by benbai
|
||||
|
||||
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
|
||||
|
||||
{{IS_RIGHT
|
||||
This program is distributed under LGPL Version 3.0 in the hope that
|
||||
it will be useful, but WITHOUT ANY WARRANTY.
|
||||
}}IS_RIGHT
|
||||
*/
|
||||
package org.zkoss.addon.chosenbox;
|
||||
|
||||
/**
|
||||
* Specified this in lang.xml, such that ZK knows what lang-addon.xml is associated
|
||||
* with chosenbox.
|
||||
*
|
||||
*/
|
||||
public class Version {
|
||||
/** Returns the version UID.
|
||||
*/
|
||||
public static final String UID = "1.0.0";
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 871 B |
Binary file not shown.
After Width: | Height: | Size: 396 B |
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,159 @@
|
|||
<%@ taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" %>
|
||||
|
||||
.z-chosenbox {
|
||||
background-color: #FFF;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #EEEEEE));
|
||||
background-image: -webkit-linear-gradient(center bottom, white 85%, #EEEEEE 99%);
|
||||
background-image: -moz-linear-gradient(center bottom, white 85%, #EEEEEE 99%);
|
||||
background-image: -o-linear-gradient(bottom, white 85%, #EEEEEE 99%);
|
||||
background-image: -ms-linear-gradient(top, #FFFFFF 85%,#EEEEEE 99%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EEEEEE',GradientType=0 );
|
||||
background-image: linear-gradient(top, #FFFFFF 85%,#EEEEEE 99%);
|
||||
|
||||
display:-moz-inline-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
<c:if test="${zk.ie < 8}">
|
||||
zoom: 1;
|
||||
display: inline;
|
||||
</c:if>
|
||||
border: 1px solid #cfcfcf;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
-ms-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
padding: 2px 5px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.z-chosenbox-focus {
|
||||
border: 1px solid #0000ff;
|
||||
}
|
||||
.z-chosenbox-sel {
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
.z-chosenbox-sel-item {
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius : 3px;
|
||||
border-radius : 3px;
|
||||
-moz-background-clip : padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip : padding-box;
|
||||
background-color: #E4E4E4;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #E4E4E4), color-stop(0.7, #EEEEEE));
|
||||
background-image: -webkit-linear-gradient(center bottom, #E4E4E4 0%, #EEEEEE 70%);
|
||||
background-image: -moz-linear-gradient(center bottom, #E4E4E4 0%, #EEEEEE 70%);
|
||||
background-image: -o-linear-gradient(bottom, #E4E4E4 0%, #EEEEEE 70%);
|
||||
background-image: -ms-linear-gradient(top, #E4E4E4 0%,#EEEEEE 70%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#E4E4E4', endColorstr='#EEEEEE',GradientType=0 );
|
||||
background-image: linear-gradient(top, #E4E4E4 0%,#EEEEEE 70%);
|
||||
color: #333;
|
||||
border: 1px solid #B4B4B4;
|
||||
margin: 0px 0px 0px 4px;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
<c:if test="${zk.ie < 8}">
|
||||
display: inline;
|
||||
zoom: 1;
|
||||
</c:if>
|
||||
font-size: ${fontSizeM};
|
||||
font-family: ${fontFamilyC};
|
||||
font-style: normal;
|
||||
padding-bottom: 0px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.z-chosenbox-sel-item-cnt {
|
||||
font-size: 13px;
|
||||
font-family: 'lucida grande',tahoma,verdana,arial,sans-serif;
|
||||
padding: 0px 2px;
|
||||
display: inline-block;
|
||||
<c:if test="${zk.ie < 8}">
|
||||
display: inline;
|
||||
</c:if>
|
||||
font-size: ${fontSizeM};
|
||||
font-family: ${fontFamilyC};
|
||||
}
|
||||
.z-chosenbox-sel-item-focus {
|
||||
background: #D4D4D4;
|
||||
border-color: #FED700;
|
||||
}
|
||||
.z-chosenbox-del-btn {
|
||||
width: 12px;
|
||||
height: 13px;
|
||||
font-size: 1px;
|
||||
background: url(${c:encodeURL('~./chosenbox/img/chosen-sprite.png')}) right top no-repeat;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
display: inline-block;
|
||||
<c:if test="${zk.ie < 8}">
|
||||
display: inline;
|
||||
background: url(${c:encodeURL('~./chosenbox/img/chosen-del.gif')}) no-repeat;
|
||||
zoom: 1;
|
||||
</c:if>
|
||||
|
||||
}
|
||||
.z-chosenbox-inp {
|
||||
color: #666;
|
||||
background: transparent !important;
|
||||
border: 0 !important;
|
||||
|
||||
outline: 0;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow : none;
|
||||
-o-box-shadow : none;
|
||||
box-shadow : none;
|
||||
|
||||
padding: 3px 5px 3px 5px;
|
||||
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
<c:if test="${zk.ie < 8}">
|
||||
display: inline;
|
||||
</c:if>
|
||||
font-size: ${fontSizeM};
|
||||
font-family: ${fontFamilyC};
|
||||
}
|
||||
.z-chosenbox-txcnt {
|
||||
display: none;
|
||||
font-size: ${fontSizeM};
|
||||
font-family: ${fontFamilyC};
|
||||
white-space: nowrap;
|
||||
}
|
||||
.z-chosenbox-pp {
|
||||
position: absolute;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-top: 0;
|
||||
font-family: ${fontFamilyC};
|
||||
font-size: ${fontSizeM};
|
||||
font-weight: normal;
|
||||
margin:0;
|
||||
overflow:auto;
|
||||
|
||||
-webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
|
||||
-moz-box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||
-o-box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||
box-shadow : 0 4px 5px rgba(0,0,0,.15);
|
||||
}
|
||||
|
||||
.z-chosenbox-pp-hidden {
|
||||
display: none;
|
||||
}
|
||||
.z-chosenbox-option {
|
||||
cursor: pointer;
|
||||
padding-top: 3px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.z-chosenbox-option-over {
|
||||
background-color: #D3EFFA;
|
||||
}
|
||||
.z-chosenbox-empty {
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.z-chosenbox-empty-creatable {
|
||||
cursor: pointer;
|
||||
background-color: #D3EFFA;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* chosenbox.js
|
||||
|
||||
Purpose:
|
||||
|
||||
Description:
|
||||
|
||||
History:
|
||||
Tue Nov 16 15:15:52 TST 2011, Created by benbai
|
||||
|
||||
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
|
||||
|
||||
This program is distributed under LGPL Version 3.0 in the hope that
|
||||
it will be useful, but WITHOUT ANY WARRANTY.
|
||||
*/
|
||||
function (out) {
|
||||
var zcls = this.getZclass(),
|
||||
uid = this.uuid;
|
||||
|
||||
out.push('<i id="', uid, '" class="',zcls,'"', (!this.isVisible() ? 'style="display:none;"' : ''), '>',
|
||||
'<input id="', uid, '-inp" class="',zcls,'-inp"', this.domAttrs_(), '></input>',
|
||||
'<div id="', uid, '-txcnt" class="',zcls,'-txcnt"></div>', // hidden field for change input width dynamically
|
||||
'<div id="', uid, '-pp" class="',zcls,'-pp ', zcls,'-pp-hidden">',
|
||||
'<div id="', uid, '-sel" class="',zcls,'-sel">');
|
||||
if (!this._renderByServer)
|
||||
this._renderItems(out);
|
||||
out.push('</div>',
|
||||
'<div id="', uid, '-empty" class="',zcls,'-empty"></div>','</div></i>');
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<package name="chosenbox" language="xul/html" depends="zul.wgt">
|
||||
<widget name="Chosenbox"/>
|
||||
</package>
|
|
@ -1421,4 +1421,32 @@ public class DB_Oracle implements AdempiereDatabase
|
|||
return info;
|
||||
return info.substring(fromIndex + 1, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String subsetClauseForCSV(String columnName, String csv) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("toTableOfVarchar2(")
|
||||
.append(columnName)
|
||||
.append(")");
|
||||
builder.append(" submultiset of ")
|
||||
.append("toTableOfVarchar2('")
|
||||
.append(csv)
|
||||
.append("')");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String intersectClauseForCSV(String columnName, String csv) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("toTableOfVarchar2(")
|
||||
.append(columnName)
|
||||
.append(")");
|
||||
builder.append(" MULTISET INTERSECT ")
|
||||
.append("toTableOfVarchar2('")
|
||||
.append(csv)
|
||||
.append("') IS NOT EMPTY");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
} // DB_Oracle
|
||||
|
|
|
@ -1145,4 +1145,32 @@ public class DB_PostgreSQL implements AdempiereDatabase
|
|||
return info;
|
||||
return info.substring(fromIndex + 1, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String subsetClauseForCSV(String columnName, String csv) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("string_to_array(")
|
||||
.append(columnName)
|
||||
.append(",',')");
|
||||
builder.append(" <@ "); //is contained by
|
||||
builder.append("string_to_array('")
|
||||
.append(csv)
|
||||
.append("',',')");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String intersectClauseForCSV(String columnName, String csv) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("string_to_array(")
|
||||
.append(columnName)
|
||||
.append(",',')");
|
||||
builder.append(" && "); //is contained by
|
||||
builder.append("string_to_array('")
|
||||
.append(csv)
|
||||
.append("',',')");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
} // DB_PostgreSQL
|
||||
|
|
Loading…
Reference in New Issue