Project

General

Profile

patch.6016.patch

Marian Edu, 02/02/2022 02:06 AM

Download (14 KB)

View differences:

new/src/com/goldencode/p2j/ui/ControlSetEntity.java 2022-02-01 14:31:53 +0000
95 95
**     RFB 20211022          Additional documentation to point out the empty string condition. Ref #4710.
96 96
**     HC  20211102          Implemented i18n support.
97 97
**     AL2 20220124          Make all control set entities to check for screen-value validity.
98
**     ME  20220201          Allow for multiple values list when setting screen-value (delimiter is used).
98 99
*/
99 100
/*
100 101
** This program is free software: you can redistribute it and/or modify
......
154 155
import java.util.*;
155 156
import java.util.function.*;
156 157
import java.util.regex.*;
158
import java.util.stream.Collectors;
159
import java.util.stream.Stream;
157 160

  
158 161
import com.goldencode.p2j.util.*;
159 162
import com.goldencode.p2j.ui.client.format.*;
......
2853 2856
   {
2854 2857
      if (inUIStmt || !internalScreenValueUsage)
2855 2858
      {
2856
         if (value instanceof character && !isValidScreenValue((character) value))
2859
         if (value instanceof character && !validateScreenValue((character) value))
2857 2860
         {
2858
            if (_isRealized() && frame != null &&
2859
                getAttr("wasRealized", () -> frame.getFrameWidget().config().wasRealized, true))
2860
            {
2861
               ErrorManager.recordOrShowError(4058, String.format(
2862
                     "Attribute SCREEN-VALUE for the %s %s has an invalid value of %s", type(),
2863
                     widgetName(), ((BaseDataType) value).isUnknown() ? "UNKNOWN" : value), false);
2864
            }
2865
            
2866 2861
            return false;
2867 2862
         }
2868 2863
      }
......
2870 2865
      return super.setScreenValue(frameBuf, value, inUIStmt);
2871 2866
   }
2872 2867
   
2868
   /**
2869
    * Validate the value(s) for SCREEN-VALUE attribute, the delimiter is used
2870
    * to split it into an array.
2871
    * 
2872
    * @param value
2873
    * The to be validated as SCREEN-VALUE attribute.
2874
    * 
2875
    * @return <code>true</code> if the value is a valid screen-value.
2876
    */
2877
   boolean validateScreenValue(character value)
2878
   {
2879
      if (!value.isUnknown())
2880
      {
2881
         char delimiter = getAttr("delimiter", () -> config.delimiter);
2882
         character[] values = TextOps.entries(character.class, value.getValue(),
2883
                  String.valueOf(delimiter));
2884

  
2885
         if (!isValidScreenValue(values))
2886
         {
2887
            if (_isRealized())
2888
            {
2889
               ErrorManager.recordOrShowWarning(4058, String.format(
2890
                        "Attribute SCREEN-VALUE for the %s %s has an invalid value of %s", type(),
2891
                        widgetName(), (value.isUnknown() ? "UNKNOWN" : value.getValue())), true,
2892
                        false, false, true);
2893
            }
2894

  
2895
            return false;
2896
         }
2897
      }
2898

  
2899
      return true;
2900
   }
2873 2901
   
2874 2902
   /**
2875 2903
    * Check if the tested value is in the control-set values.
......
2881 2909
    */
2882 2910
   protected boolean isValidScreenValue(character value)
2883 2911
   {
2884
      if (value.isUnknown() || getAttr("items", () -> config.items) == null)
2885
      {
2886
         return false;
2887
      }
2888
      
2889
      // test value
2890
      return Arrays.stream(getAttr("items", () -> config.items)).anyMatch(item -> item.getCharacterValue().equals(value));
2912
      return isValidScreenValue(new character[] { value });
2913
   }
2914
   
2915
   /**
2916
    * Check if the tested value(s) is in the control-set values.
2917
    * 
2918
    * @param    value
2919
    *           The tested value(s)
2920
    * 
2921
    * @return   True if the tested value(s) is in the control-set values, otherwise false.
2922
    */
2923
   protected boolean isValidScreenValue(character... values)
2924
   {
2925
      if (values == null || values.length == 0)
2926
      {
2927
         return false;
2928
      }
2929
         
2930
      ControlSetItem[] items = getAttr("items", () -> config.items);
2931
      
2932
      if (items == null)
2933
      {
2934
         return false;
2935
      }
2936
      
2937
      for (character value : values)
2938
      {
2939
         if (!value.isUnknown() && !Arrays.stream(items).anyMatch(item -> CompareOps._isEqual(item.getCharacterValue(), value)))
2940
         {
2941
            return false;
2942
         }
2943
      }
2944

  
2945
      return true;
2891 2946
   }
2892 2947
   
2893 2948
   /**
new/src/com/goldencode/p2j/ui/SelectionListWidget.java 2022-02-02 06:52:36 +0000
56 56
**     VVT 20220120          Fixed: setting SCROLLBAR-HORIZONTAL and/or SCROLLBAR-VERTICAL for a realized
57 57
**                           widget must be rejected with the warning 4053. See #5937-53.
58 58
**     AL2 20220124          Check screen-value validity through ControlSetEntity.
59
**     ME  20220201          Handle multiple values list in set screen-value.
59 60
*/
60 61
/*
61 62
** This program is free software: you can redistribute it and/or modify
......
112 113

  
113 114
package com.goldencode.p2j.ui;
114 115

  
116
import java.util.Arrays;
117
import java.util.Set;
118
import java.util.stream.Collectors;
119

  
115 120
import com.goldencode.p2j.util.*;
116 121

  
117 122
/**
......
908 913
   @Override 
909 914
   boolean setScreenValue(ScreenBuffer frameBuf, Object value, boolean inUIStmt)
910 915
   {
911
      if (inUIStmt && frameBuf.getWidgetValue(getId()) != null)
912
      {
913
         if (value == null || (
914
             value instanceof BaseDataType && 
915
             !(value instanceof character) &&
916
             ((BaseDataType) value).isUnknown()))
916
      if (!(value instanceof character))
917
      {
918
         // we can't set non-character value to selection list
919
         return false;
920
      }
921

  
922
      character cvalue = (character) value;
923

  
924
      if (!cvalue.isUnknown() && cvalue.toJavaType().length() == 0)
925
      {
926
         cvalue.setUnknown();
927
      }
928

  
929
      return super.setScreenValue(frameBuf, cvalue, inUIStmt);
930
   }
931
   
932
   /**
933
    * Validate the value(s) for SCREEN-VALUE attribute, the delimiter is used
934
    * to split it into an array.
935
    * 
936
    * If valid the SCREEN-VALUE will be updated to reflect the resulting value.
937
    * 
938
    * @param value
939
    *        The to be validated as SCREEN-VALUE attribute.
940
    * 
941
    * @return <code>true</code> if the value is a valid screen-value.
942
    */
943
   @Override
944
   boolean validateScreenValue(character value)
945
   {
946
      if (super.validateScreenValue(value))
947
      {
948
         // if valid update the screen-value 
949
         if (!value.isUnknown())
917 950
         {
918
            // we can set unknown value to character selection list
919
            return false;
951
            String delimiter = String.valueOf(getAttr("delimiter", () -> config.delimiter));
952
            character[] values = TextOps.entries(character.class, value.getValue(), delimiter);
953
            ControlSetItem[] items = getAttr("items", () -> config.items);
954

  
955
            // resulting screen-value might be different due to:
956
            // - reorder based on item's index
957
            // - only first item with given value is selected (case insensitive)
958
            if (getAttr("multiple", () -> config.multiple))
959
            {
960
               // for multiple selection existing selection is kept (append)
961
               Set<Integer> selection = Arrays.stream(frame.getSelection(this)).map(i -> i + 1)
962
                        .boxed().collect(Collectors.toSet());
963

  
964
               for (character val : values)
965
               {
966
                  for (ControlSetItem item : items)
967
                  {
968
                     if (CompareOps._isEqual(val, item.getCharacterValue()))
969
                     {
970
                        selection.add(item.getItemId());
971
                        break;
972
                     }
973
                  }
974
               }
975

  
976
               character newValue = new character(
977
                        Arrays.stream(items).filter(item -> selection.contains(item.getItemId()))
978
                                 .map(item -> item.getCharacterValue().getValue())
979
                                 .collect(Collectors.joining(delimiter)));
980

  
981
               value.assign(newValue);
982
            }
983
            else
984
            {
985
               // last value from the list win
986
               for (ControlSetItem item : items)
987
               {
988
                  if (CompareOps._isEqual(values[values.length - 1], item.getCharacterValue()))
989
                  {
990
                     value.assign(item.getCharacterValue());
991
                     break;
992
                  }
993
               }
994
            }
920 995
         }
921 996
         
922
         if (value instanceof character && 
923
            ((character) value).toJavaType().length() == 0)
924
         {
925
            return false;
926
         }
927
      }
928
      
929
      if (!inUIStmt                        && 
930
          value instanceof character       && 
931
          !((character) value).isUnknown() && 
932
           ((character) value).toJavaType().length() == 0)
933
      {
934
         ((character) value).setUnknown();
935
      }
936
      
937
      return super.setScreenValue(frameBuf, value, inUIStmt);
997
         return true;
998
      }
999
      
1000
      return false;
938 1001
   }
939
   
940
   
1002

  
941 1003
   /**
942 1004
    * Check if the tested value is valid for screen-value.
1005
    * Unknown is a valid option as it will clear the selection.
943 1006
    * 
944 1007
    * @param    value
945 1008
    *           The tested value
946 1009
    * 
947 1010
    * @return   True if the tested value is valid for screen-value, otherwise false.
948 1011
    */
1012
   @Override
949 1013
   protected boolean isValidScreenValue(character value)
950 1014
   {
951 1015
      // it is valid to assign unknown to screen-value of a selection list widget
new/src/com/goldencode/p2j/ui/client/SelectionList.java 2022-02-01 13:19:56 +0000
72 72
**     VVT 20220119          Minor annotation and javadoc fixes.
73 73
**     VVT 20220126          setSelectionMode() now returns boolean indicating any change was done
74 74
**                           by the method call. See #5937.
75
**     ME  20220201          Force refresh on <code>afterConfigUpdate</code> if model is empty 
76
**                           (configuration items needs to be parsed during initialization).
75 77
*/
76 78
/*
77 79
** This program is free software: you can redistribute it and/or modify
......
480 482

  
481 483
         // 4gl API does allows only to replace all list items at once, which regenerates *all* item IDs.
482 484
         // As the result, it is sufficient to compare only the first item IDs here.
483
         needToResetView |= newItems[0].getItemId() != oldItems[0].getItemId();
485
         needToResetView |= newItems[0].getItemId() != oldItems[0].getItemId() || list.model().size() == 0;
484 486
      }
485 487

  
486 488
      if (needToResetView)
new/src/com/goldencode/p2j/ui/client/SelectionListBody.java 2022-02-01 13:17:24 +0000
127 127
**                           toggleCurrentRowSelection(). selectItem() method is now unused and
128 128
**                           removed. Method getDefaultEvent() overloaded. Several #5937 issues fixed.
129 129
**                           Class members sorted.
130
**     ME  20220201          Handle multiple values list in set screen-value.
130 131
*/
131 132
/*
132 133
** This program is free software: you can redistribute it and/or modify
......
801 802
   public void setValue(BaseDataType value)
802 803
   {  
803 804
      selected  = false;
804
      initValue = new character();
805
      
806 805
      boolean doRepaint = false;
807 806
      
808 807
      if (value.isUnknown())
809
         return;
810
      
811
      selectionClear();
812
      
813
      if (value instanceof character)
814 808
      {
815
         String itemList = ((character) value).getValue();
816
         
817
         char[] delim = new char[1];
818
         delim[0] = config.delimiter;
819
         String d = new String(delim);
820
         
821
         String[] elem = itemList.split(d);
822
         
823
         boolean isChui = ThinClient.getInstance().isChui();
824
         
825
         for (String element : elem)
826
         {
827
            BaseDataType val = 
828
               DisplayFormat.instanceOfType(isChui, config.dataType, element);
829
            
830
            if (setSingleValue(val))
831
               doRepaint = true;
832
         }
809
         selectionClear();
810
         doRepaint = true;
833 811
      }
834 812
      else
835
         doRepaint = setSingleValue(value);
836

  
813
      {
814
         if (value instanceof character)
815
         {
816
            String itemList = ((character) value).getValue();
817
            
818
            char[] delim = new char[1];
819
            delim[0] = config.delimiter;
820
            String d = new String(delim);
821
            
822
            String[] elem = itemList.split(d);
823
            
824
            boolean isChui = ThinClient.getInstance().isChui();
825
            
826
            for (String element : elem)
827
            {
828
               BaseDataType val = 
829
                  DisplayFormat.instanceOfType(isChui, config.dataType, element);
830
               
831
               if (setSingleValue(val))
832
                  doRepaint = true;
833
            }
834
         }
835
         else
836
         {
837
            doRepaint = setSingleValue(value);
838
         }
839
      }
840
      
837 841
      if (doRepaint)
838 842
      {
839 843
         repaint();
840
         initValue = value; 
844
         initValue = getScreenValue();
841 845
      }
842 846
   }
843 847
   
......
1105 1109
         return false;
1106 1110
      }
1107 1111
      
1108
      boolean doRepaint = false;
1112
      if (selectionMode() == ListSelectionModel.SINGLE_SELECTION)
1113
      {
1114
         selectionClear();
1115
      }
1109 1116
      
1110 1117
      for (int i = 0; i < items.length; i++)
1111 1118
      {
......
1113 1120
         {
1114 1121
            select(i,i);
1115 1122
            
1116
            if (first() >= 0)
1117
               ensureRowVisible(first());
1123
            if (i >= 0)
1124
               ensureRowVisible(i);
1118 1125
            
1119
            doRepaint = true;
1126
            // only first entry that matches the value is selected
1127
            return true;
1120 1128
         }
1121 1129
      }
1122 1130
      
1123
      return doRepaint;
1131
      return false;
1124 1132
   }
1125
}
1133
}