Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Custom CanvasItem and onSelectionChanged

    I wrote a custom TileListItem element in which I use FlowLayout with a lot of buttons. What should I do so that when the button is clicked, the OnSelectionChanged event handler is called.

    I looked in Telegrid how the OnSelectionChanged event handler is registered, but I didn't find how to call it.
    Last edited by Hirn; 24 Oct 2023, 01:11.

    #2
    SelectionChanged is an event related to ListGrids, and you haven’t mentioned how a ListGrid is involved here.

    If you take a look at the CanvasItem samples you can see how you can contribute values to the surrounding form.

    Comment


      #3
      The thing is, I don't use ListGrid in any way, but my component is very similar to TileGrid. Which I had to abandon due to the inability to use AutoFit for items.
      But I would really like to use OnSelectionChanged, because it would make further development much easier for me.


      Click image for larger version  Name:	Zwischenablage-3.jpg Views:	0 Size:	12.7 KB ID:	271193


      Click image for larger version  Name:	Zwischenablage-2.jpg Views:	0 Size:	55.5 KB ID:	271195
      Last edited by Hirn; 24 Oct 2023, 20:50.

      Comment


        #4
        Sorry, we’re not following what you want here. There’s no ListGrid but you want SelectionChanged to fire.. from where exactly?

        What would it simplify? You have your array of buttons, each with a click handler presumably, so if you need to run some logic in response to a button being clicked, it’s nearly a one-liner to do that.

        Comment


          #5
          Hi Hirn,

          please have a look at the CanvasItem main docs.
          I think shouldSaveValue:true plus a call to storeValue() is what you need.
          change(d) handlers on the item itself as well as on the DynamicForm should fire then.
          Like you say, this is not related to ListGrid at all, so the use of the word onSelectionChanged is very misleading.

          Best regards
          Blama
          Last edited by Blama; 24 Oct 2023, 21:44.

          Comment


            #6
            I don't have a SelectionChanged handler. But you correctly noticed that I have an array of buttons and there is an onClick handler for them. So I wanted the SelectionChanged handler to be called from it.

            Comment


              #7
              Hi Blama
              this is not exactly what I need. I use should Save Value and storeValue() to display buttons in my component, and I need a handler for selecting these buttons.

              Comment


                #8
                You are talking about the situation when a user clicks and activates/deactivates one of the buttons, right?
                Doesn‘t DynamicForm.addItemChangedHandler() do this for you?

                Best regards
                Blama

                Comment


                  #9
                  I have a Dynamic Form.addItemChangedHandler() triggered to change the number and quality of buttons in the component, and I need a handler that responds to the selection of these buttons. So that I can make an add Selection Change Handler in my component and it will trigger when the buttons are pressed. I found how to add this handler to the component, but unfortunately I didn't find how to call it.
                  Code:
                  public HandlerRegistration addSelectionChangedHandler(com.smartgwt.client.widgets.tile.events.SelectionChangedHandler handler) {
                          if(getHandlerCount(com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType()) == 0) setupSelectionChangedEvent();
                          return doAddHandler(handler, com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType());
                      }
                  
                      private native void setupSelectionChangedEvent() /*-{
                          var obj;
                          var selfJ = this;
                          var hasDefaultHandler;
                          var selectionChanged = $entry(function(){
                              var param = {"_this": this, "record" : arguments[0], "state" : arguments[1]};
                              var event = @com.smartgwt.client.widgets.tile.events.SelectionChangedEvent::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
                              selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
                              selfJ.@com.smartgwt.client.widgets.tile.TileGrid::handleTearDownSelectionChangedEvent()();
                              if (hasDefaultHandler) this.Super("selectionChanged", arguments);
                          });
                          if(this.@com.smartgwt.client.widgets.BaseWidget::isCreated()()) {
                              obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
                              hasDefaultHandler = $wnd.isc.isA.Function(obj.getProperty("selectionChanged"));
                              obj.addProperties({selectionChanged: selectionChanged});
                          } else {
                              obj = this.@com.smartgwt.client.widgets.BaseWidget::getConfig()();
                              var scClassName = this.@com.smartgwt.client.widgets.BaseWidget::scClassName;
                              hasDefaultHandler = $wnd.isc.isA.Function($wnd.isc[scClassName].getInstanceProperty("selectionChanged"));
                              obj.selectionChanged = selectionChanged ;
                          }
                      }-*/;

                  Comment


                    #10
                    Sorry, this does not make sense to me.
                    ItemChanged is what happens when you change the selected button by activating/deactivating them.
                    No need for any other handlers.
                    ClickHandlers in the Buttons: Call CanvasItem.storeValue()
                    ItemChangedHandler in DynamicForm: Do your logic.

                    Perhaps explain on a higher level what you are trying to build, if this is not what you want.

                    Best regards
                    Blama

                    Comment


                      #11
                      I have almost solved my problem, but there is one nuance left...
                      I have the code...
                      Code:
                          public HandlerRegistration addSelectionChangedHandler(com.smartgwt.client.widgets.tile.events.SelectionChangedHandler handler) {
                              if(getHandlerCount(com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType()) == 0) setupSelectionChangedEvent();
                              return doAddHandler(handler, com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType());
                          }
                      
                          private native void setupSelectionChangedEvent() /*-{
                              var obj;
                              var selfJ = this;
                              var hasDefaultHandler;
                              var selectionChanged = $entry(function(){
                                  var param = {"_this": this, "record" : arguments[0], "state" : arguments[1]};
                                  var event = @com.smartgwt.client.widgets.tile.events.SelectionChangedEvent::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
                                  selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
                                  if (hasDefaultHandler) this.Super("selectionChanged", arguments);
                              });
                              if(this.@com.smartgwt.client.widgets.BaseWidget::isCreated()()) {
                                  obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
                                  hasDefaultHandler = $wnd.isc.isA.Function(obj.getProperty("selectionChanged"));
                                  obj.addProperties({selectionChanged: selectionChanged});
                              } else {
                                  obj = this.@com.smartgwt.client.widgets.BaseWidget::getConfig()();
                                  var scClassName = this.@com.smartgwt.client.widgets.BaseWidget::scClassName;
                                  hasDefaultHandler = $wnd.isc.isA.Function($wnd.isc[scClassName].getInstanceProperty("selectionChanged"));
                                  obj.selectionChanged = selectionChanged;
                              }
                          }-*/;
                      
                          private native void doSelectionChanged(Record record, Boolean state) /*-{
                              var obj;
                              var selfJ = this;
                              obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
                              hasDefaultHandler = $wnd.isc.isA.Function(obj.getProperty("selectionChanged"));
                              if (hasDefaultHandler) obj.selectionChanged(record, state);
                          }-*/;
                      but if I use

                      Code:
                      TileListItem projectLanguagesList = new TileListItem("projectLanguages", Strings.get("projectLanguages"));
                      projectLanguagesList.addSelectionChangedHandler(new com.smartgwt.client.widgets.tile.events.SelectionChangedHandler() {
                                  @Override
                                  public void onSelectionChanged(SelectionChangedEvent event) {
                                      int i = 0;
                                  }
                              });
                      that 's in my line
                      var scClassName = this.@com.smartgwt.client.widgets.BaseWidget::scClassName;

                      scClassName == undefined
                      and the program crashes with an error

                      and if I use such code, then everything works fine
                      Code:
                      TileListItem projectLanguagesList = new TileListItem("projectLanguages", Strings.get("projectLanguages"));
                      
                      form.setFields(projectLanguagesList);
                      addMember(form);
                      
                      projectLanguagesList.addSelectionChangedHandler(new com.smartgwt.client.widgets.tile.events.SelectionChangedHandler() {
                                  @Override
                                  public void onSelectionChanged(SelectionChangedEvent event) {
                                      int i = 0;
                                  }
                              });
                      I understand why the error crashes, but I haven't found how to fix it yet



                      Comment


                        #12
                        Hi Hirn


                        TileListItem is your CanvasItem subclass, correct? And are you manually adding a method that takes a com.smartgwt.client.widgets.tile.events.SelectionChangedHandler as parameter with your addSelectionChangedHandler? This does seem very strange to me and I'd assume this is not the way forward, even if it is almost working.

                        Again, describe what you want to do on a higher level. Also, big screenshots with remarks will help.

                        Best regards
                        Blama

                        Comment


                          #13
                          HI Blama
                          >>
                          This does seem very strange to me and I'd assume this is not the way forward, even if it is almost working

                          it's not whether it seems strange or not. For further development, I need exactly this functionality. Now I have received a working version (though not a beautiful one). I will finish the rest as needed.

                          >>TileListItem is your CanvasItem subclass, correct?
                          Exactly. If you are interested, I give the code of my component below...

                          Code:
                          package com.cbtl.widgets.editors;
                          
                          import java.lang.reflect.Array;
                          import java.util.Arrays;
                          
                          import com.cbtl.utils.JsUtils;
                          import com.cbtl.widgets.CONSTANT;
                          import com.google.gwt.event.shared.HandlerRegistration;
                          import com.google.gwt.user.client.ui.PopupPanel;
                          import com.smartgwt.client.types.Overflow;
                          import com.smartgwt.client.types.SelectionType;
                          import com.smartgwt.client.widgets.Button;
                          import com.smartgwt.client.widgets.Canvas;
                          import com.smartgwt.client.widgets.Label;
                          import com.smartgwt.client.widgets.events.ClickEvent;
                          import com.smartgwt.client.widgets.events.ClickHandler;
                          import com.smartgwt.client.widgets.events.DoubleClickEvent;
                          import com.smartgwt.client.widgets.events.DoubleClickHandler;
                          import com.smartgwt.client.widgets.form.DynamicForm;
                          import com.smartgwt.client.widgets.form.fields.CanvasItem;
                          import com.smartgwt.client.widgets.form.fields.FormItemIcon;
                          import com.smartgwt.client.widgets.form.fields.events.IconClickEvent;
                          import com.smartgwt.client.widgets.form.fields.events.IconClickHandler;
                          import com.smartgwt.client.widgets.layout.FlowLayout;
                          import com.smartgwt.client.data.Record;
                          
                          import com.smartgwt.client.bean.*;
                          
                          @BeanFactory.FrameworkClass
                          @BeanFactory.ScClassName("TileListItem")
                          
                          public class TileListItem extends CanvasItem {
                              private FlowLayout tileList;
                              private String[] valueMap;
                              private String[] selectedValues;
                              private PopupPanel selectionPanel;
                              private TileListItem selectionList;
                              public TileListItem parentList;
                              private int pickListWidth;
                              private int pickListtHeight;
                          
                              public TileListItem (String name) {
                                  scClassName = "TileListItem";
                                  setName(name);
                                  itit();
                              }
                          
                              public TileListItem(String name, String title) {
                                  scClassName = "TileListItem";
                                  setName(name);
                                  setTitle(title);
                                  itit();
                              }
                          
                              private void itit() {
                                  setEndRow(true);
                                  setStartRow(true);
                                  setColSpan("*");
                                  setShouldSaveValue(true);
                                  tileList = new FlowLayout();
                                  tileList.setWidth("100%");
                                  tileList.setStyleName("inputTextField");
                                  tileList.setLayoutMargin(CONSTANT.PADDING);
                                  tileList.setTileMargin(CONSTANT.PADDING);
                                  tileList.setAutoHeight();
                                  tileList.setOverflow(Overflow.VISIBLE);
                          
                                  tileList.addDoubleClickHandler(new DoubleClickHandler() {
                                      @Override
                                      public void onDoubleClick(DoubleClickEvent event) {
                                          if(valueMap != null) {
                                                 createSelectionPanel();
                                          }
                                      }
                                  });
                          
                                  setCanvas(tileList);
                                  setShouldSaveValue(true);
                              }
                          
                              private void clearValues(String... values) {
                                  Canvas[] children = tileList.getChildren();
                                  if(children != null && children.length > 0) {
                                      for(Canvas child:children) {
                                          if(JsUtils.indexOf(values, child.getTitle()) == -1) {
                                              tileList.removeChild(child);
                                          }
                                      }
                                  }
                              }
                          
                              public CanvasItem setCanSelect(Boolean canSelect) {
                                  return (CanvasItem)setAttribute("canSelect", canSelect);
                              }
                          
                              public Boolean getCanSelect() {
                                  Boolean result = getAttributeAsBoolean("canSelect", true);
                                  return result == null ? false : result;
                              }
                          
                              public void setValueMap(String... values) {
                                  valueMap = values;
                                  if(values != null && values.length > 0) {
                                      FormItemIcon editIcon = new FormItemIcon();
                                      editIcon.setSrc(CONSTANT.BUTTONS_ICONS + "edit.png");
                                      editIcon.setShowOver(false);
                                      editIcon.setTabIndex(-1);
                                      setIcons(editIcon);
                                      addIconClickHandler(new IconClickHandler() {
                                          public void onIconClick(IconClickEvent event) {
                                                 createSelectionPanel();
                                          }
                                      });
                                  } else {
                                      setIcons(new FormItemIcon[] {});
                                  }
                              }
                          
                              public void setValue(String value) {
                                  setValues(new String[] {value});
                              }
                          
                              public void showValues(String[] newValues) {
                                  clearValues(newValues);
                                  Boolean multiple = getMultiple();
                                  String name = getName();
                                  Boolean canSelect = getCanSelect();
                                  String[] values = JsUtils.castObjectToStrings(getValue());
                                  for(String value:newValues) {
                                      if(canSelect) {
                                          if(values == null || JsUtils.indexOf(values, value) == -1) {
                                              Button item = new Button(value);
                                              item.setPadding(CONSTANT.PADDING);
                                              item.setAutoFit(true);
                                              item.setCanFocus(false);
                                              item.setShowRollOver(false);
                                              if(multiple) {
                                                  item.setActionType(SelectionType.CHECKBOX);
                                              } else {
                                                  item.setActionType(SelectionType.RADIO);
                                                  item.setRadioGroup(name);
                                              }
                                              item.addClickHandler(new ClickHandler() {
                                                  @Override
                                                  public void onClick(ClickEvent event) {
                                                      Button buttom = (Button) event.getSource();
                                                      String value = buttom.getTitle();
                                                      if(selectedValues == null) {
                                                          selectedValues = new String[] {};
                                                      }
                                                      if(buttom.getSelected()) {
                                                          Array.set(selectedValues, selectedValues.length, value);
                                                      } else {
                                                          JsUtils.removeArrayValue(selectedValues, value);
                                                      }
                                                      if(parentList != null) {
                                                          parentList.showValues(selectedValues);
                                                          parentList.storeValue(selectedValues);
                                                      } else {
                                                          Record record = new Record();
                                                          record.setAttribute(CONSTANT.TITLE, value);
                                                          doSelectionChanged(record, buttom.isSelected());
                                                      }
                                                  }
                                              });
                                              tileList.addTile(item);
                                          }
                                      } else {
                                          if(values == null || JsUtils.indexOf(values, value) == -1) {
                                              Label item = new Label(value);
                                              item.setHeight(25);
                                              item.setAutoFit(true);
                                              item.setStyleName("textButton");
                                              item.setWrap(false);
                                              tileList.addTile(item);
                                          }
                                      }
                                  }
                              }
                          
                              public void setValues(String[] newValues) {
                                  showValues(newValues);
                                  super.setValue(newValues);
                              }
                          
                              public String[] getSelectValues() {
                                  if(selectedValues != null) {
                                      return Arrays.copyOf(selectedValues, selectedValues.length);
                                  } else {
                                      return new String[] {};
                                  }
                              }
                          
                              public void selectValue(String value) {
                                  selectValue(value, true);
                              }
                          
                              public void selectValue(String value, Boolean update) {
                                  if(getMultiple()) {
                                      if(selectedValues == null) {
                                          selectedValues = new String[] {};
                                      }
                                      Array.set(selectedValues, selectedValues.length, value);
                                  } else {
                                      selectedValues = new String[] {value};
                                  }
                                  selectValues(selectedValues, update);
                              }
                          
                              public void selectValues(String[] values) {
                                  selectValues(values, true);
                              }
                          
                              public void selectValues(String[] values, Boolean update) {
                                  if(getCanSelect()) {
                                      if(getMultiple()) {
                                          selectedValues = values;
                                      } else {
                                          selectedValues = new String[] {values[0]};
                                      }
                                      if(update) {
                                          Canvas[] children = tileList.getChildren();
                                          for(Canvas child:children) {
                                              Button button = (Button) child;
                                              Boolean select = JsUtils.indexOf(selectedValues, button.getTitle()) != -1;
                                              button.setSelected(select);
                                          }
                                      }
                                  }
                              }
                          
                              public Object getValues() {
                                  return super.getValue();
                              }
                          
                              public void setPickListWidth(int value) {
                                  pickListWidth = value;
                              }
                          
                              public int getPickListWidth() {
                                  return pickListWidth;
                              }
                          
                              public void setPickListHeight(int value) {
                                  pickListtHeight = value;
                              }
                          
                              public int getPickListHeight() {
                                  return pickListtHeight;
                              }
                          
                              private void createSelectionPanel() {
                                  DynamicForm form = new DynamicForm();
                                  form.setWidth("100%");
                                  form.setMargin(0);
                                  form.setCellPadding(0);
                                  form.setAutoHeight();
                          
                                  selectionList = new TileListItem(getName() + "selectionList");
                                  selectionList.parentList = this;
                                  selectionList.setWidth("100%");
                                  selectionList.setShowTitle(false);
                                  selectionList.setMultiple(getMultiple());
                                  selectionList.setCanSelect(true);
                                  selectionList.setValues(valueMap);
                          
                                  form.setFields(selectionList);
                          
                                  selectionPanel = new PopupPanel(true);
                                  selectionPanel.setStyleName("dropDownPanel");
                                  int width = getPickListWidth();
                                  if(width == 0) {
                                      width = tileList.getWidth();
                                  }
                                  selectionPanel.setWidth(Integer.toString(width));
                                  selectionPanel.setModal(false);
                                  selectionPanel.setWidget(form);
                                  selectionPanel.show();
                                  int x = tileList.getAbsoluteLeft();
                                  int y = tileList.getAbsoluteTop() + tileList.getBottom() - tileList.getTop();
                                  selectionPanel.setPopupPosition(x, y);
                                  selectionList.selectValues(JsUtils.castObjectToStrings(getValue()));
                              }
                          
                              public HandlerRegistration addSelectionChangedHandler(com.smartgwt.client.widgets.tile.events.SelectionChangedHandler handler) {
                                  if(getHandlerCount(com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType()) == 0) setupSelectionChangedEvent();
                                  return doAddHandler(handler, com.smartgwt.client.widgets.tile.events.SelectionChangedEvent.getType());
                              }
                          
                              private native void setupSelectionChangedEvent() /*-{
                                  var obj;
                                  var selfJ = this;
                                  var hasDefaultHandler;
                                  var selectionChanged = $entry(function(){
                                      var param = {"_this": this, "value" : arguments[0], "state" : arguments[1]};
                                      var event = @com.smartgwt.client.widgets.tile.events.SelectionChangedEvent::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
                                      selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
                                      if (hasDefaultHandler) this.Super("selectionChanged", arguments);
                                  });
                                  if(this.@com.smartgwt.client.widgets.BaseWidget::isCreated()()) {
                                      obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
                                      hasDefaultHandler = $wnd.isc.isA.Function(obj.getProperty("selectionChanged"));
                                      obj.addProperties({selectionChanged: selectionChanged});
                                  } else {
                                      obj = this.@com.smartgwt.client.widgets.BaseWidget::getConfig()();
                                      var scClassName = this.@com.smartgwt.client.widgets.form.fields.FormItem::scClassName;
                                      var classValue = $wnd.isc[scClassName];
                                      hasDefaultHandler = $wnd.isc.isA.Function($wnd.isc[scClassName].getInstanceProperty("selectionChanged"));
                                      obj.selectionChanged = selectionChanged;
                                  }
                              }-*/;
                          
                              private native void doSelectionChanged(Record record, Boolean state) /*-{
                                  var obj;
                                  var selfJ = this;
                                  obj = this.@com.smartgwt.client.widgets.BaseWidget::getJsObj()();
                                  hasDefaultHandler = $wnd.isc.isA.Function(obj.getProperty("selectionChanged"));
                                  if (hasDefaultHandler) obj.selectionChanged(record, state);
                              }-*/;
                          }

                          Comment


                            #14
                            This is not a correct approach and relies on undocumented internals. It is likely to be broken just by minor patches, and very unlikely to survive an actual version upgrade.

                            We and Blama have already given you the correct approach multiple times.

                            It sounds like you have some crufty code elsewhere that absolutely requires a SelectionChanged handler, and you are reluctant to fix this code. Well, you need to - the code you are writing right now is completely throwaway and of negative value.

                            Comment


                              #15
                              >>It sounds like you have some crufty code elsewhere that absolutely requires a SelectionChanged handler, and you are reluctant to fix this code. Well, you need to - the code you are writing right now is completely throwaway and of negative value.

                              it's absolutely not that I don't want to fix my code.
                              I have such a task in front of me... write a component in which a list of elements was selected from a drop-down list as in (SelectItem) and additionally this selected list should be selectable.
                              If it were not for the last condition, then your proposal with storeValue() would be more suitable than ever.
                              Unfortunately, it's not me who sets the tasks for myself, but my superiors.


                              Comment

                              Working...