1. #1
    Ext User
    Join Date
    Jan 2010
    Posts
    19
    Vote Rating
    0
    grandanat is on a distinguished road

      0  

    Question Custom CheckBoxSelectionModel - change default icon

    Custom CheckBoxSelectionModel - change default icon


    Simplified problem:
    I have a grid with a CheckBoxSelectionModel and i want to change default checkbox icons with my own, programmatically. Basically i think the best solution would be to extend gxt CheckBoxSelectionModel class and create a method setIcon(String imageUrl) that points to my image. I tried following code in my CustomCheckBoxSelectionModel ctor but it dowsn't work properly, it just append my image right to default image.
    Code:
    public CustomCheckBoxSelectionModel(String myImage) {
        super();
        this.getColumn().setRenderer(new GridCellRenderer<M>() {
          public String render(M model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<M> store,
              Grid<M> grid) {
            config.cellAttr = "rowspan='2'";
            config.style = "background-image: url(" + myImage + ");";
            return "<div class='x-grid3-row-checker'> </div>";
          }
        });
      }
    I just want to replace this image :
    Code:
    .x-grid3-row-checker, .x-grid3-hd-checker {
        background-image:url(../images/default/grid/row-check-sprite.gif);
    }
    With my own one. Can anyone advice me how to approach the problem ?


    Extended problem.
    If i want to use a larger image then toggle selection area will have to be increased. Although size of this area is defined din css file. How do i change it dynamically in code ? I don;t want to override css, since i don;t want to apply this change to all grids that uses a checkbox selection model.
    Another abandoned solution was to use a custom identifier instead of checker

    Code:
    void replaceDivs() {
        grid.addListener(Events.ViewReady, new Listener<ComponentEvent>() {
          @Override
          public void handleEvent(ComponentEvent be) {
    
            El header = grid.getView().getHeader().el();
            El headerBody = header.getChild(1);
            header.setInnerHtml(header.getInnerHtml().replace("-checker", "-mychecker"));
            El hdc = headerBody.child("div.x-grid3-hd-checker");
            if (hdc != null) {
              hdc.child("x-grid3-hd-checker");
              hdc.getId();
              hdc.getParent().setStyleName(hdc.getParent().getStyleName().replace("-checker", "-mychecker"));
              hdc.getChild(0).getParent().setStyleName(
                  hdc.getChild(0).getParent().getStyleName().replace("-checker", "-mychecker"));
            }
          }
        });
      }
    This solution worked better but is not really ok. i shouldn't have different different css classes for same thing(even icons are different).

  2. #2
    Ext User
    Join Date
    Jan 2010
    Posts
    19
    Vote Rating
    0
    grandanat is on a distinguished road

      0  

    Default


    After one more day i've progressed but still not have a full working solution.
    At this point all i have to change only background-position for "selected" image (checker-on)
    So, i set my custom image to header( in constructor)
    Code:
    this.getColumn().setRenderer(new GridCellRenderer<M>() {
          public String render(M model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<M> store,
              Grid<M> grid) {
            config.cellAttr = "rowspan='2'";
            return "<div class='x-grid3-row-checker' style=' height: " + (imageSize + 2 * 2) + "px; background-image: " + imageURL + "; '>&#160;</div>";
          }
        });
    I set my image to rows after ViewReady event
    Code:
    El hdc = grid.getView().getHeader().el().getChild(1).child("div.x-grid3-hd-checker");
        hdc.dom.getStyle().setBackgroundImage(imageURL);
    , change checker size according to row height and place image in center to look nice
    Code:
    hdc.setStyleAttribute("height", this.rowHeight - 2);
        this.padding  = (this.rowHeight - 2 - this.imageSize)/2;
        hdc.setStyleAttribute("background-position", padding + "px " + padding + "px");
    THE PROBLEM:
    When a selection is changed, html structure is builded dynamically in code(in CheckBoxSelectionModel implementation)

    Code:
    private void setChecked(boolean checked) {
        if (grid.isViewReady()) {
          El hd = grid.getView().innerHd.child("div.x-grid3-hd-checker");
          if (hd != null) {
            hd.getParent().setStyleName("x-grid3-hd-checker-on", checked);
          }
        }
      }
    After this call html element checker is replaced with checke checker-on. and the new background-position value is taken from css, to display checked image.

    HTML Code:
    .x-grid3-row-selected .x-grid3-row-checker,.x-grid3-hd-checker-on .x-grid3-hd-checker,.x-grid3-row-checked .x-grid3-row-checker
      {
      background-position: -23px 2px;
    }
    Now the problem is that offset my image has other value (my images are larger) so i haven't access to this css checker-on background-position to change it. So i have to change it but i don't know how. Any advice will be more than welcome.

    Another question would be if my approach is correct, to change css values programmatically in the code? Unfortunately I didn't a better solution.

  3. #3
    Ext User
    Join Date
    Jan 2010
    Posts
    19
    Vote Rating
    0
    grandanat is on a distinguished road

      0  

    Default


    Adopted solution:

    Code:
    package mypackage.controls;
    
    import com.extjs.gxt.ui.client.core.El;
    import com.extjs.gxt.ui.client.data.ModelData;
    import com.extjs.gxt.ui.client.event.ComponentEvent;
    import com.extjs.gxt.ui.client.event.Events;
    import com.extjs.gxt.ui.client.event.Listener;
    import com.extjs.gxt.ui.client.store.ListStore;
    import com.extjs.gxt.ui.client.store.StoreEvent;
    import com.extjs.gxt.ui.client.widget.Component;
    import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel;
    import com.extjs.gxt.ui.client.widget.grid.ColumnData;
    import com.extjs.gxt.ui.client.widget.grid.Grid;
    import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
    
    public class CustomCheckBoxSelectionModel<M extends ModelData> extends CheckBoxSelectionModel<M> {
    
      protected String       imageURL    = "url(\"/res/images/selectColumnModel.gif\")";
      protected int          imageSize   = 24;
      protected int          padding     = 2;
      protected int          leftPadding = padding;
      protected int          rowHeight   = imageSize + padding * 2;
    
      public CustomCheckBoxSelectionModel(String image, int size) {
        super();
        this.imageURL = image;
        this.imageSize = size;
        this.rowHeight = this.imageSize + padding * 2;
        initConfig();
      }
    
      public CustomCheckBoxSelectionModel() {
        super();
        initConfig();
      }
    
      private void initConfig() {
        this.getColumn().setId("checker");
        this.getColumn().setWidth(rowHeight + 2);
        this.getColumn().setRenderer(new GridCellRenderer<M>() {
          public String render(M model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<M> store,
              Grid<M> grid) {
            config.cellAttr = "rowspan='2'";
            return "<div class='x-grid3-row-checker' style=' height: " + rowHeight + "px; background-image: " + imageURL
                + "; '> </div>";
          }
        });
      }
    
      @Override
      public void init(Component component) {
        super.init(component);
        modifyElement();
      }
    
      private void modifyElement() {
        grid.addListener(Events.ViewReady, new Listener<ComponentEvent>() {
          @Override
          public void handleEvent(ComponentEvent be) {
            replaceBackgroundImage();
          }
        });
      }
    
      void replaceBackgroundImage() {
    
        El hdc = grid.getView().getHeader().el().getChild(1).child("div.x-grid3-hd-checker");
        hdc.dom.getStyle().setBackgroundImage(imageURL);
        hdc.setStyleAttribute("height", this.rowHeight - 2);
        hdc.setStyleAttribute("background-position", padding + "px " + padding + "px");
      }
    
      @Override
      protected void onSelectChange(M model, boolean select) {
        super.onSelectChange(model, select);
    
        if (grid.isViewReady()) {
          boolean change = getSelection().size() == grid.getStore().getCount();
          changeHeaderOffset(change);
          changeRowOffset(grid.getStore().indexOf(model), change);
        }
      }
    
      @Override
      protected void onClear(StoreEvent<M> se) {
        super.onClear(se);
        changeHeaderOffset(false);
      }
    
      private void changeHeaderOffset(boolean select) {
        if (select/* && leftPadding == padding */) {
          leftPadding = padding - 12 - imageSize;
        } else/* if(leftPadding != padding) */{
          leftPadding = padding;
        }
    
        El hdc = grid.getView().getHeader().el().getChild(1).child("div.x-grid3-hd-checker");
        hdc.setStyleAttribute("background-position", leftPadding + "px " + padding + "px");
      }
    
      private void changeRowOffset(int index, boolean select) {
    
        El hdr = El.fly(grid.getView().getRow(index)).child("div.x-grid3-row-checker");
        int itemPadding = padding;
        if (isSelected(grid.getStore().getAt(index))) {
          itemPadding = padding - 12 - imageSize;
        }
    
        hdr.setStyleAttribute("background-position", itemPadding + "px " + padding + "px");
    
      }
    
    }
    Please feel free to make any comments or suggestions.