Announcement

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

    Dynamic Ribbon (Respond to Changes in Window Size)

    Hi Isomorphic. I'm trying to implement a custom Ribbon that responds to window resizing (adding more rows for small screen/window sizes), since I'm not aware of such capability being supported currently. My ResizeHandler fires correctly and invokes my repondToWindowChanges() method, but when I try to setNumRows to 2 for my RibbonGroup elements, I can't seem to get them to redraw and display accordingly. Here is the code:

    Code:
        public void respondToWindowChanges() {
    
            double ribbonWidth = 0;
            for(RibbonGroup group: getRibbonGroupsByVisibility("visible")){
                // the value is replaced intentionally to that the final value is the left coordinate
                // of the rightmost group, which is the last group that needs to fit on screen. 
                ribbonWidth = group.getPageLeft();
            }
    
            if(ribbonWidth > Page.getWidth()){
                for(RibbonGroup group: getRibbonGroupsByVisibility("visible")){
                    group.setNumRows(2);
                }    
                this.markForRedraw();
            }
        }
    I tried calling redraw() and markForRedraw() on the custom Ribbon, after setting all groups numRows to 2. I also tried calling these two methods on the individual groups. Nothing seems to be taken by the control when it is redrawn. Can you please help me figuring our what am I missing here?

    Do I need to destroy the ribbon and create it again for these rowNum changes to take effect?

    I am working on Chrome Version 49.0.2623.87 m, SmartClient Version: v10.1p_2016-03-18/Pro Deployment (built 2016-03-18).

    Thanks in advance for any help you can provide on this!

    #2
    There's no builtin way to have the groups in a RibbonBar reflow as you'd like at runtime.

    However, you don't need to destroy the RibbonBar or anything that dramatic - the easiest way is probably something like this;

    1) have a method like getControls(groupName) that returns a set of new controls - use this to populate your groups initially
    2) when you want to force your relayout, just update numRows as you are doing, and then also call group.setControls(getControls(groupName))

    That will work as you expect.

    Note that having the method return *new* controls is necessary, because setControls() removes *and destroys* the previous control-set.
    Last edited by Isomorphic; 22 Mar 2016, 00:32.

    Comment


      #3
      As always, thanks Isomorphic for your valuable help. This indeed works as desired.

      By the way, IMHO you probably could document this behavior in the setNumRows method, as a requirement for dynamic (on the fly) ribbon changes.

      Comment


        #4
        Hi Isomorphic. Keeping up with my custom dynamic RibbonBar, I can get the ribbon to display 1 or 2 rows of controls with your previous suggestion. This is my code so far for the function that gets called when a onResized event fires on the RibbonBar:

        Code:
        private void respondToWindowChanges() {      
            int requiredRows = (Page.getWidth() < RIBBON_WIDTH) ? 2 : 1;
            int currentRows = allRibbonGroups.get(0).getNumRows();
            if(currentRows != requiredRows){
                for(RibbonGroup group: allRibbonGroups){
                    group.setNumRows(requiredRows);
                    group.setHeight(ICON_SIZE * requiredRows * 2);
                    setGroupControls(group);
                }
                this.markForRedraw();
            }
        }
        The thing is that now the RibbonGroups are not willing to resize gracefully when I follow the next sequence:

        1. I draw my application window with my browser window maximized. By default, on big enough window sizes, my RibbonBar behaves as desired, with no customizations required:
        Click image for larger version

Name:	RibbonFullWindow.png
Views:	80
Size:	15.7 KB
ID:	236109


        2. Then I reduce the window size to less than 1024 pixels (the value for RIBBON_WIDTH constant). At this point a call to my respondToWindowChanges method is made and numRows is set to 2 for all RibbonGroups. They all display correctly, showing 2 rows of controls, and also the height of all groups is increased, to get a consistent look (all groups fill the available space in the RibbonBar). This works just fine.
        Click image for larger version

Name:	RibbonSmallWindow.png
Views:	76
Size:	17.5 KB
ID:	236110


        3. But when I increase the size of the window again, although the numRows is correctly changed to 1 again, and all RibbonGroups display their controls in just one row, the size of some of the RibbonGroups is the same they had when they were displaying their controls in 2 rows. This won't happen with RibbonGroups with just one control, as you can see in the image below.
        Click image for larger version

Name:	RibbonFullWindowAgain.png
Views:	75
Size:	16.5 KB
ID:	236111


        So the question here is: how can I make the RibbonGroups take the specified height after a window resize happens? I tried using setHeight (with all variations: min, max, default) on both RibbonGroups and the RibbonBar, but nothing seems to work. I also tried removing all members from RibbonBar and adding them again, with no luck. I would really appreciate your help here!
        Last edited by carlossierra; 22 Mar 2016, 20:14.

        Comment


          #5
          We went ahead and extended the doc for numRows, so that it points to the new API we just added - ribbonGroup.reflowControls().

          This new API does what you've been trying to do, and is more effiecient because it doesn't destroy the original items. You can test it out tomorrow, with code like this:

          Code:
          group.setNumRows(2);
          group.reflowControls();
          Note that this change also includes a fix for the height problem you mentioned most recently - the ribbon as a whole will now correctly size to content vertically.
          Last edited by Isomorphic; 22 Mar 2016, 23:21.

          Comment


            #6
            Thanks Isomorphic. Indeed, it works as expected now.

            Comment


              #7
              In case anyone is interested, here is my final respondToWindowChanges code:

              Code:
              private static final int RIBBON_WIDTH = 1024;
              private static final int ICON_SIZE = 22;
              
              // when a new RibbonGroup is created, it is added to this list, to make it easy to iterate 
              // on them when functions like respondToWindowChanges are called
              private ArrayList<RibbonGroup> allRibbonGroups = new ArrayList<RibbonGroup>();
              ...
              
              private void respondToWindowChanges() {       
                  int requiredRows = (Page.getWidth() > RIBBON_WIDTH) ? 1 : 2;
                  int currentRows = allRibbonGroups.get(0).getNumRows();
                  if(currentRows != requiredRows){
                      for(RibbonGroup group: allRibbonGroups){
                          group.setNumRows(requiredRows);
                          group.setHeight(ICON_SIZE * requiredRows * 2);
                          group.reflowControls();
                      }
                  }
              }

              Comment

              Working...
              X