Announcement

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

  • Isomorphic
    replied
    This continues to be a broken and unsupportable approach, for the same reason as we have explained before: internal, undocumented and unsupported JSNI details have been copied and pasted into your application code.

    The underlying issue continues to be the same as stated multiple times previously: you are talking about something being "selectable" and unilaterally assuming that this means there must be a JSNI-based OnSelectionChanged handler. This is neither a requirement for any normal notion of "selectable" nor is it something coming from our product.

    If there is something in your codebase that has a notion of "selectable" and requires hacks like this, then you need to change that part of your application code, rather than proceeding with a hack that is simply going to break.

    As we have previously stated, any apparent "progress" in this direction is illusory: you are literally making negative progress, putting yourself in a worse position than when you started.

    Bottom line: no one should copy this code, and this poster is demonstrating how not to work with Support: this poster is simply assuming various things and not explaining them. The communication problem is so bad here that we are starting to expect trolling, because we are literally 36 posts in, and even with heroic attempts by Blama to address the problem via painstaking interrogation of the OP, we still have no explanation from the OP as to what "selectable" means to him and why he assumes this means a hacked-up OnSelectionChanged handler that copies undocumented internals into application code.

    Leave a comment:


  • kesarteraa
    replied
    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.
    indigo card
    jjsploit.click
    Last edited by kesarteraa; 3 Nov 2023, 03:17.

    Leave a comment:


  • Hirn
    replied
    Well, I wrote the version I wanted. I think it won't break after the next updates.
    Code:
    package com.cbtl.widgets.editors;
    
    import java.lang.reflect.Array;
    import java.util.Arrays;
    
    import com.cbtl.events.tile.SelectionChangedEvent;
    import com.cbtl.events.tile.SelectionChangedHandler;
    import com.cbtl.utils.JsUtils;
    import com.cbtl.widgets.CONSTANT;
    import com.google.gwt.core.client.JavaScriptObject;
    import com.google.gwt.event.logical.shared.CloseEvent;
    import com.google.gwt.event.logical.shared.CloseHandler;
    import com.google.gwt.event.shared.HandlerRegistration;
    import com.google.gwt.user.client.Timer;
    import com.google.gwt.user.client.Window;
    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.events.FocusChangedEvent;
    import com.smartgwt.client.widgets.events.FocusChangedHandler;
    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.form.fields.events.ShowValueEvent;
    import com.smartgwt.client.widgets.form.fields.events.ShowValueHandler;
    import com.smartgwt.client.widgets.layout.FlowLayout;
    
    public class TileListDeveloperItem extends CanvasItem {
        private static String STYLE = "inputTextField";
        private FlowLayout tileList;
        private String[] valueMap;
        private String[] selectedValues;
        private PopupPanel selectionPanel;
        private TileListDeveloperItem selectionList;
        private int pickListWidth;
        private int pickListtHeight;
    
        public TileListDeveloperItem (JavaScriptObject obj) {
            super(obj);
            init();
        }
    
        public TileListDeveloperItem (String name) {
            super(name);
            init();
        }
    
        public TileListDeveloperItem(String name, String title) {
            super(name, title);
            init();
        }
    
        private void init() {
            setColSpan("*");
            setShouldSaveValue(true);
    
            selectedValues = new String[] {};
    
            tileList = new FlowLayout();
            tileList.setWidth("100%");
            tileList.setCanFocus(true);
            tileList.setStyleName(STYLE);
            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();
                    }
                }
            });
    
            tileList.addFocusChangedHandler(new FocusChangedHandler() {
                @Override
                public void onFocusChanged(FocusChangedEvent event) {
                    if(event.getHasFocus()) {
                        tileList.setStyleName(STYLE + "Focused");
                    } else {
                        tileList.setStyleName(STYLE);
                    }
                }
            });
    
            addShowValueHandler(new ShowValueHandler() {
                @Override
                public void onShowValue(ShowValueEvent event) {
                    String[] values = JsUtils.castObjectToStrings(event.getDataValue());
                    if(values != null) {
                        showValues(values);
                    }
                }
            });
    
            setCanvas(tileList);
    
        }
    
        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 String[] getValue() {
            return JsUtils.castObjectToStrings(super.getValue());
        }
    
        public void setValue(String value) {
            setValues(new String[] {value});
        }
    
        public String[] getValues() {
            return JsUtils.castObjectToStrings(super.getValue());
        }
    
        public void setValues(String[] values) {
            super.setValue(values);
        }
    
        private String[] clearValues(String... values) {
            String[] oldValues = new String[] {};
            Canvas[] children = tileList.getChildren();
            if(children != null && children.length > 0) {
                for(Canvas child:children) {
                    String title = child.getTitle();
                    if(JsUtils.indexOf(values, title) == -1) {
                        tileList.removeChild(child);
                    } else {
                        Array.set(oldValues, oldValues.length, title);
                    }
                }
            }
            return oldValues;
        }
    
        public void showValues(String[] newValues) {
            String[] oldValues = clearValues(newValues);
            Boolean multiple = getMultiple();
            String name = getName();
            Boolean canSelect = getCanSelect();
            for(String value:newValues) {
                if(canSelect) {
                    if(oldValues == null || JsUtils.indexOf(oldValues, 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();
                                selectValue(value, buttom.getSelected());
                                   doSelect(value, buttom.isSelected());
                            }
                        });
                        tileList.addTile(item);
                    }
                } else {
                    if(oldValues == null || JsUtils.indexOf(oldValues, value) == -1) {
                        Label item = new Label(value);
                        item.setHeight(25);
                        item.setAutoFit(true);
                        item.setStyleName("textButton");
                        item.setWrap(false);
                        tileList.addTile(item);
                    }
                }
            }
        }
    
        public CanvasItem setCanSelect(Boolean canSelect) {
            return (CanvasItem)setAttribute("canSelect", canSelect);
        }
    
        public Boolean getCanSelect() {
            Boolean result = getAttributeAsBoolean("canSelect", true);
            return result == null ? false : result;
        }
    
        public String[] getSelectedValues() {
            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 state) {
            if(getCanSelect()) {
                if(selectedValues == null) {
                    selectedValues = new String[] {};
                }
                if(getMultiple()) {
                    if(state) {
                        Array.set(selectedValues, selectedValues.length, value);
                    } else {
                        JsUtils.removeArrayValue(selectedValues, value);
                    }
                } else {
                    if(state) {
                        selectedValues = new String[] {value};
                    }
                }
            }
        }
    
        public void selectValues(String[] values) {
            if(getCanSelect()) {
                if(getMultiple()) {
                    selectedValues = values;
                } else {
                    selectedValues = new String[] {values[0]};
                }
                updateSelection();
            }
        }
    
        public void updateSelection() {
            Canvas[] children = tileList.getChildren();
            for(Canvas child:children) {
                Button button = (Button) child;
                Boolean select = JsUtils.indexOf(selectedValues, button.getTitle()) != -1;
                button.setSelected(select);
            }
        }
    
        public HandlerRegistration addSelectionChangedHandler(SelectionChangedHandler selectionChangedHandler) {
            return doAddHandler(selectionChangedHandler, SelectionChangedEvent.getType());
        }
    
        public native void doSelect(String value, Boolean state) /*-{
            var selfJ = this;
            var param = {"_this":this, "value":arguments[0], "state":arguments[1]};
            var event = @com.cbtl.events.tile.SelectionChangedEvent::new(Lcom/google/gwt/core/client/JavaScriptObject;)(param);
            selfJ.@com.smartgwt.client.widgets.BaseWidget::fireEvent(Lcom/google/gwt/event/shared/GwtEvent;)(event);
        }-*/;
    
        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 TileListDeveloperItem(getName() + "selectionList");
            selectionList.setWidth("100%");
            selectionList.setShowTitle(false);
            selectionList.setMultiple(getMultiple());
            selectionList.setCanSelect(true);
            selectionList.setValues(valueMap);
            selectionList.selectValues(getValues());
            selectionList.addSelectionChangedHandler(new com.cbtl.events.tile.SelectionChangedHandler() {
                @Override
                public void onSelectionChanged(com.cbtl.events.tile.SelectionChangedEvent event) {
                    String[] values = selectionList.selectedValues;
                    showValues(values);
                    storeValue(values);
                    Timer timer = new Timer() {
                        @Override
                        public void run() {
                            cancel();
                            setPanelPosition();
                        }
                    };
                    timer.scheduleRepeating(300);
                }
            });
    
            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(true);
            selectionPanel.setWidget(form);
            selectionPanel.addCloseHandler(new CloseHandler<PopupPanel>() {
                @Override
                public void onClose(CloseEvent<PopupPanel> event) {
                    selectionList = null;
                    selectionPanel = null;
                }
            });
            selectionPanel.show();
            selectionPanel.setVisible(false);
            selectionList.updateSelection();
    
            Timer timer = new Timer() {
                @Override
                public void run() {
                    cancel();
                    setPanelPosition();
                }
            };
            timer.scheduleRepeating(50);
    
        }
    
        public void setPanelPosition() {
            int x = tileList.getAbsoluteLeft();
            int h = tileList.getBottom() - tileList.getTop();
            int y = tileList.getAbsoluteTop();
            int h1 = selectionList.tileList.getBottom() - selectionList.tileList.getTop();
            int wh = Window.getClientHeight() - Window.getScrollTop();
            if((y + h + h1) < wh) {
                selectionPanel.setPopupPosition(x, y + h);
            } else {
                selectionPanel.setPopupPosition(x, y - h1);
            }
            selectionPanel.setVisible(true);
        }
    }
    and here are examples of the use of components

    Code:
    TileListDeveloperItem projectLanguagesList = new TileListDeveloperItem("projectLanguages", Strings.get("projectLanguages"));
            projectLanguagesList.setWidth("100%");
            projectLanguagesList.setWrapTitle(false);
            projectLanguagesList.setMultiple(true);
            projectLanguagesList.setCanSelect(true);
            projectLanguagesList.setValueMap(languages);
            projectLanguagesList.setValues(projectLanguages);
            projectLanguagesList.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent event) {
                     .....
                }
            });
            projectLanguagesList.addSelectionChangedHandler(new com.cbtl.events.tile.SelectionChangedHandler() {
                @Override
                public void onSelectionChanged(com.cbtl.events.tile.SelectionChangedEvent selectionChangedEvent) {
                 .....
                }
            });
    Last edited by Hirn; 28 Oct 2023, 00:03.

    Leave a comment:


  • Hirn
    replied
    >>Why do you need that? I meant if the storeValue() approach works.

    To be honest, I haven't even tried. The prospect of comparing 2 arrays of objects to find out whether the selection has changed or not does not appeal to me

    Leave a comment:


  • Blama
    replied
    Why do you need that? I meant if the storeValue() approach works.

    Leave a comment:


  • Hirn
    replied
    >>But does the rest work for you?

    so far it fits, but if (as promised by Isomorphic) my solution breaks, then I will have to invent something new

    Leave a comment:


  • Blama
    replied
    Hi Hirn,

    I'd open a new thread for that.
    But does the rest work for you?

    Best regards
    Blama

    Leave a comment:


  • Hirn
    replied
    I don't know whether to open a new topic or who can answer here...
    Is there an opportunity to add an event onEventResizeMove to CanvasItem.
    this is necessary for the correct positioning of the drop-down list when scrolling the screen or if the size of the top list changes
    Last edited by Hirn; 26 Oct 2023, 03:51.

    Leave a comment:


  • Blama
    replied
    Why is it important to know that?
    You'd always have DynamicForm.oldValues. If this is about some logic that should happen to persisted data, you can't really rely on that - imagine having two browser windows open that both do changes. In this case, compare the values serverside and act on the difference, if needed.

    Leave a comment:


  • Hirn
    replied
    >>You just change your widgets as needed when sth. is clicked and call storeValue().

    and then to find out in onchange whether the item was selected or added? I wonder why we don't do this in the List Grid? This is also possible if you only respond to onFetchData.

    Leave a comment:


  • Blama
    replied
    Ok, then store this big string via storeValue() (and work with it in ShowValueHandler to build the 1st list):
    Code:
    values = ["ES", "DE", "EN"], selectedValues = ["DE", "EN"]
    I don't see any remaining problem. You just change your widgets as needed when sth. is clicked and call storeValue().

    Leave a comment:


  • Hirn
    replied
    >>OK, so the values are not the same?

    exactly

    >>Then your value format changes, that's everything. Instead of:
    >>["ES", "DE", "EN"]
    >>you store
    >>["ES,0", "DE,1", "EN,0"]
    >>to show a list of ES, DE, EN on load via ShowValueHandler, but only DE activated.

    no, I have it saved like this for the top list right now...
    values = ["ES", "DE", "EN"]
    selectedValues = ["DE", "EN"]

    if I didn't have to react to selection events in the top list, then I would just store values as an array of objects {value:"de", selected:true}
    and if I react only to storeValue(), then I won't know if an item has been added to the top list or it has been selected
    Last edited by Hirn; 26 Oct 2023, 02:59.

    Leave a comment:


  • Blama
    replied
    OK, so the values are not the same?

    You select values from the bottom list AND THEN one can activate or deactivate them in the top list?

    Then your value format changes, that's everything. Instead of:
    Code:
    ["ES", "DE", "EN"]
    you store
    Code:
    ["ES,0", "DE,1", "EN,0"]
    to show a list of ES, DE, EN on load via ShowValueHandler, but only DE activated.

    And you call storeValue() from both lists - from the point of view of the CanvasItem it does not care whatever Widgets you build. It only cares about calls your to storeValue() and your ShowValueHandler.

    Best regards
    Blama

    Leave a comment:


  • Hirn
    replied
    the drop-down list appears when you click on the icon on the right or double-click on the top list. When a drop-down list appears, it is filled with values from the ValueMap of the top list and at the same time all items from the top list are selected and if I select new or deselect old ones in the drop-down list, the list of items in the top list changes. I do this using storeValue() for the top list. That is, storeValue() is already occupied in the top list and I need a new property and event to select values in the top list.

    >>Display of CanvasItem with data from the DB on load of the form: Build 1st list in your addShowValueHandler.

    I also found this and I'm already using it in the new version of the component

    Leave a comment:


  • Blama
    replied
    These selections are the same, correct?
    You show the bottom list once the item gets focus or something like that, correct?

    So when you build the bottom list, create the buttons that are already in the value of the item (= in the top list) as selected. On click on those items in the 2nd list you act on both lists.
    Deactivate in 2nd list: Remove from 1st list and call storeValue()
    Activate in 2nd list: Add to 1st list and call storeValue()

    Display of CanvasItem with data from the DB on load of the form: Build 1st list in your addShowValueHandler.

    Possible enhancement: On click of a button in 1st list, remove it from 1st list, deactivate it in 2nd list (only needed if the list is currently being shown) and call storeValue().

    Leave a comment:

Working...
X