Announcement

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

    12.0 VLayout + DynamicForm sizing issues on larger content

    Hi Isomorphic,

    along with this testcase there is another problem/question w.r.t. sizing, see this testcase (v12.0p_2020-04-27):

    My issues here are:
    1. The width displayed in the "debug"-Label telling about all the Widgets-width is are the same. The value for DynamicForm never changes, even if the widget clearly does. Perhaps this numbers don't refer to the drawn width, but I think they must be somehow accessible
    2. Resize of VLayout to it's maxWidth is never triggered (e.g. if you start and click "Very long title")
    3. DynamicForm looses it's right-padding (e.g. if you start and click "Very long title")
    4. DynamicForm.maxWidth seems to be ignored when there is a long title
    What I'm trying to accomplish is a DynamicForm that "always looks good", also with unexpectedly long (I18n) titles, meaning:
    • padding always present
    • width extension if needed until a certain DynamicForm.maxWidth
    • if this width makes it necessary to resize the parent VLayout, do so until it's maxWidth
    • if content is too big and wrapping doesn't help, cut off (not clear where the clipping should be happening)
    I'm relatively sure I'm not doing something wrong here in the code, but if I am, that of course would be great.

    Best regards
    Blama

    Code:
    isc.DynamicForm.create({
        ID: "myDF",
        width: 500,
        maxWidth: 600,
        backgroundColor: "yellow",
        clipItemTitles: false,
        wrapItemTitles: false,
        numCols: 2,
        colWidths: ["*", "60"],
        isGroup: true,
        groupTitle: "DynamicForm group",
        border:"1px solid blue",
        padding:50,
        fields: [
            {name: "enabled",
             title: "Enabled?",
             type: "boolean",
             width: "*",
             labelAsTitle: true,
            },
            {name: "subject",
             title: "Short text",
             type: "text",
             width: "*",
            },
            {name: "amount",
             title: "Amount",
             type: "integer",
             width: "*",
             editorType: "SpinnerItem",
            }
        ],
        updateFieldTitle: function (text) {
           this.getField("subject").setProperty('title', text);
           this.redraw();
           widthsLabel.update();
    }
    
    });
    
    isc.Button.create({
        ID: "shortTitle",
        width: 100,
        title: "Short title",
        click: "myDF.updateFieldTitle('Shrt ttl')"
    });
    
    isc.Button.create({
        ID: "mediumTitle",
        width: 100,
        title: "Medium title",
        click: "myDF.updateFieldTitle('Medium title')"
    });
    
    isc.Button.create({
        ID: "longTitle",
        width: 100,
        title: "Long title",
        click: "myDF.updateFieldTitle('Kinda long title with some details')"
    });
    
    isc.Button.create({
        ID: "veryLongTitle",
        width: 100,
        title: "Very long title",
        click: "myDF.updateFieldTitle('Crazy annoyingly loooooooooong title because of a i18n text waaaaaaaaaaaaaay longer than assumed')"
    });
    
    isc.Button.create({
        ID: "singleLetterTitle",
        width: 100,
        title: "Single letter title",
        click: "myDF.updateFieldTitle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')"
    });
    
    isc.Button.create({
        ID: "clipItemTitles",
        width: 140,
        title: "clipItemTitles: true",
        click: "myDF.setProperty('clipItemTitles', true); myDF.redraw(); widthsLabel.update();"
    });
    
    isc.Button.create({
        ID: "noClipItemTitles",
        width: 140,
        title: "clipItemTitles: false",
        click: "myDF.setProperty('clipItemTitles', false); myDF.redraw(); widthsLabel.update();"
    });
    
    isc.Button.create({
        ID: "wrapTitle",
        width: 140,
        title: "wrapItemTitles: true",
        click: "myDF.setProperty('wrapItemTitles', true); myDF.redraw(); widthsLabel.update();"
    });
    
    isc.Button.create({
        ID: "noWrapTitle",
        width: 140,
        title: "wrapItemTitles: false",
        click: "myDF.setProperty('wrapItemTitles', false); myDF.redraw(); widthsLabel.update();"
    });
    
    isc.HLayout.create({
        ID: "buttonsLayout",
        members: [shortTitle, mediumTitle, longTitle, veryLongTitle, singleLetterTitle],
        membersMargin: 10,
        height: 20,
        width: "100%",
    });
    
    isc.HLayout.create({
        ID: "buttonsLayout2",
        members: [clipItemTitles, noClipItemTitles, wrapTitle, noWrapTitle],
        membersMargin: 10,
        height: 20,
        width: "100%",
    });
    
    isc.Label.create({
        ID: "widthsLabel",
        width: 500, height: 40,
        border: "1px solid grey",
        update: function () {
           this.setContents("VLayout width: "                + myVL.width           + " / " + myVL.getVisibleWidth()           + "<br/>" +
                            "DynamicForm width: "            + myDF.width           + " / " + myDF.getVisibleWidth()           + "<br/>" + 
                            "shortTitle Button width: "      + shortTitle.width     + " / " + shortTitle.getVisibleWidth()     + "<br/>" + 
                            "clipItemTitles Button width: "  + clipItemTitles.width + " / " + clipItemTitles.getVisibleWidth() + "<br/>" + 
                            Math.random());
        }
    });
    
    isc.VLayout.create({
        ID: "myVL",
        members: [myDF, buttonsLayout, buttonsLayout2, widthsLabel],
        membersMargin: 10,
        backgroundColor: "#eee",
        padding: 10,
        isGroup: true,
        groupTitle: "VLayout group",
        border:"1px solid blue",
        height: 460,
        width: 700,
        maxWidth: 800,
        overflow: "auto",
    });
    
    isc.VLayout.create({
        ID: "outerVL",
        members: [myVL],
        membersMargin: 10,
        backgroundColor: "#aaa",
        padding: 10,
        isGroup: true,
        groupTitle: "Outer VLayout group",
        border:"1px solid blue",
        height: "100%",
        width: "100%"
    });

    #2
    1. same problem as with your other thread. canvas.getWidth() gives you the configured width, you seem to want getVisibleWidth()

    2 & 4. we don't know what you're expecting here. maxWidth would not apply here - please see the docs for what this property actually does

    3. this is what browsers do when there is too much unwrappable content to fit the content and the padding - the padding is sacrificed, right side first. This is in the HTML/CSS spec. You can force the padding to be retained by putting it on a containing element, but..

    We would say you are overthinking this. If your translator translates a two-word phrase into a 600 pixel-wide sentence, you need better translators. There is no way to make a form "always look good" once someone has badly botched a translation and created a field label that is 8 times longer than other labels. No matter how the layout algorithms respond, it is going to look ridiculous.

    If you're really afraid your translators might do this kind of thing, you should set clipItemTitles - that's the only real fix.



    Comment


      #3
      Hi Isomorphic,

      thanks for the fast answer.
      Yes, this is overthinking, but also trying to understand what happens and why, so that I can actually use the framework as intended.

      1: understood
      3: understood, but not nice IMHO, see this minimal sample.
      I'd expect the combination of width: 1, overflow: "visible" always make the form big enough for the padding:50.
      Also, if you increase the padding value to around 140, then there a right padding start to appear, but not as big as the left padding.
      Code:
      isc.DynamicForm.create({
          ID: "myDF",
          width: 1,
          overflow: "visible",
          backgroundColor: "yellow",
          numCols: 2,
          colWidths: ["*", "60"],
          isGroup: true,
          groupTitle: "DynamicForm group",
          border:"1px solid blue",
          padding:50, // Try 150 - then there is some right padding?!
          fields: [
              {name: "enabled",
               title: "Enabled?",
               type: "boolean",
               width: "*",
               labelAsTitle: true,
              },
              {name: "subject",
               title: "Short text",
               type: "text",
               width: "*",
              }
          ]
      });
      2+4: I think I might be able to solve a lot of what I want if 3 were working as written above, that is always show the right padding width: 1, overflow: "visible".
      Wr.t. maxWidth (which I might use incorrectly here): Perhaps then it is not what I want. How would you solve this use case (perhaps it involves resize handlers?):
      1. Form (with or without padding gets bigger until a maximum size for this DF)
      2. Layout containing the Form gets bigger until a maximum size for this Layout
      3. If either content is too big, show a scrollbar
      As I imagine, this is a combination of width: 1, overflow: "visible, but auto if larger than x".

      Best regards
      Blama

      Comment


        #4
        With #3, you seem to be complaining about the CSS standard? Wrong place to post about that :) As we explained, padding on an outer element would be maintained.

        You request seems to just describe what happens if you put the form & layout into an overflow:"auto" container.

        Comment


          #5
          Hi Isomorphic,

          thanks, what you you are suggesting with the container is working:
          Code:
          myVL:
             no overflow settings
          
          outerVL:
              width: 750,
              overflow: "auto",
          W.r.t. the DynamicForm I don't understand this. Somehow this is under your control and you make it big enough already for padding on left/top/bottom.
          Please have a look at the screenshots.
          Of course I don't know exactly what's happening there and but it seems that there is padding of 100 relative to the small 26x67 box.
          If now the box were bigger and the containing box with the yellow backgound also were bigger, this should look as I want it to, shouldn't it?
          This setting with width: 1, overflow: "visible" is what you suggest in the Overflow-docs.
          Any other way of accomplishing this is also very welcome, but to me this seems correct.

          Thank you & Best regards
          Blama


          Click image for larger version

Name:	Browser F12 tools.png
Views:	118
Size:	14.9 KB
ID:	262266

          Comment


            #6
            We covered this already:

            3. this is what browsers do when there is too much unwrappable content to fit the content and the padding - the padding is sacrificed, right side first. This is in the HTML/CSS spec. You can force the padding to be retained by putting it on a containing element, but..
            We're not doing anything special about the left padding, it's just that the CSS spec says that when there isn't enough room, right padding is sacrificed first.

            And we've already explained how to avoid this if the padding is considered critical.

            Comment


              #7
              Hi Isomorphic,

              I was asking because I never saw left padding sacrificed and therefore assumed you must be doing something in your width calculation here that includes this padding.
              But I got it working now with DynamicForm + Layout for padding + Layout for scrollbars from width x on, thank you!

              I do have another question though, again in the Layout department (for learning purposes)
              Please see the testcase below where the passing is working now.
              How can I archive that one can see all the DynamicForm contents vertically (=no vertical scrollbar), while still having the next widget of the main layout directly below? My solutions don't work:
              1. Leave away LayoutSpacers in outerVL -> Next widgets are not directly below the form
              2. Give a specific number as height / minHeight to scrollVL -> might be too much
              I think that either of these things could solve the problem:
              • Have Layout distribute space to items with scrollbars on the length axis (member of a VLayout has vertical scrollbar) before dividing it between % and * sized members.
                I think I saw a setting yesterday that was talking about on which "level" space gets assigned to a widget yesterday, but can't find it today. Perhaps this is related?
              • Have a separate setting for setHOverflow() and setVOverflow(): This way I could set vOverflow: "visible" on scrollVL.
              • Something like ListGrid.autoFitData: "vertical", but for Canvas? (ListGrid.autoFitData: "both" is kinda Canvas.overflow: "visible")
              Or is it possible today already (without Handlers) and I did not find out how, yet?

              Thank you & Best regards
              Blama

              Code:
              isc.DynamicForm.create({
                  ID: "myDF",
                  height: 1,
                  width: 1,
                  overflow: "visible",
                  backgroundColor: "#FF0;",
                  clipItemTitles: false,
                  wrapItemTitles: false,
                  numCols: 2,
                  colWidths: ["*", 100],
                  fields: [
                      {name: "enabled",
                       title: "Enabled?",
                       type: "boolean",
                       width: "*",
                       labelAsTitle: true,
                      },
                      {name: "subject",
                       title: "Short text",
                       type: "text",
                       width: "*",
                      },
                      {name: "amount",
                       title: "Amount",
                       type: "integer",
                       width: "*",
                       editorType: "SpinnerItem",
                      }
                  ],
                  updateFieldTitle: function (text) {
                     this.getField("subject").setProperty('title', text);
                     this.redraw();
                     widthsLabel.update();
              }
              });
              
              isc.VLayout.create({
                  ID: "paddingVL",
                  members: [myDF],
                  groupTitle: "Padding VLayout",
                  backgroundColor: "#CC0;",
                  padding:50,
                  height: 1,
                  width: 1,
                  overflow: "visible",
              });
              
              isc.VLayout.create({
                  ID: "scrollVL",
                  backgroundColor: "#AA0;",
                  members: [paddingVL],
                  maxWidth: 600,
                  height: "100%",
                  maxHeight: 600,
                  overflow: "auto",
              });
              
              isc.Button.create({
                  ID: "shortTitle",
                  width: 100,
                  title: "Short title",
                  click: "myDF.updateFieldTitle('Shrt ttl')"
              });
              
              isc.Button.create({
                  ID: "mediumTitle",
                  width: 100,
                  title: "Medium title",
                  click: "myDF.updateFieldTitle('Medium title')"
              });
              
              isc.Button.create({
                  ID: "longTitle",
                  width: 100,
                  title: "Long title",
                  click: "myDF.updateFieldTitle('Kinda long title with some details')"
              });
              
              isc.Button.create({
                  ID: "veryLongTitle",
                  width: 100,
                  title: "Very long title",
                  click: "myDF.updateFieldTitle('Crazy annoyingly looooo­ooooong title because of a i18n text waaaaaaa­aaaaaaay longer than assumed')"
              });
              
              isc.Button.create({
                  ID: "singleLetterTitle",
                  width: 100,
                  title: "Single letter title",
                  click: "myDF.updateFieldTitle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')"
              });
              
              isc.Button.create({
                  ID: "clipItemTitles",
                  width: 140,
                  title: "clipItemTitles: true",
                  click: "myDF.setProperty('clipItemTitles', true); myDF.redraw(); widthsLabel.update();"
              });
              
              isc.Button.create({
                  ID: "noClipItemTitles",
                  width: 140,
                  title: "clipItemTitles: false",
                  click: "myDF.setProperty('clipItemTitles', false); myDF.redraw(); widthsLabel.update();"
              });
              
              isc.Button.create({
                  ID: "wrapTitle",
                  width: 140,
                  title: "wrapItemTitles: true",
                  click: "myDF.setProperty('wrapItemTitles', true); myDF.redraw(); widthsLabel.update();"
              });
              
              isc.Button.create({
                  ID: "noWrapTitle",
                  width: 140,
                  title: "wrapItemTitles: false",
                  click: "myDF.setProperty('wrapItemTitles', false); myDF.redraw(); widthsLabel.update();"
              });
              
              isc.HLayout.create({
                  ID: "buttonsLayout",
                  members: [shortTitle, mediumTitle, longTitle, veryLongTitle, singleLetterTitle],
                  membersMargin: 10,
                  height: 20,
                  width: "100%",
              });
              
              isc.HLayout.create({
                  ID: "buttonsLayout2",
                  members: [clipItemTitles, noClipItemTitles, wrapTitle, noWrapTitle],
                  membersMargin: 10,
                  height: 20,
                  width: "100%",
              });
              
              isc.Label.create({
                  ID: "widthsLabel",
                  width: 500, height: 40,
                  border: "1px solid grey",
                  update: function () {
                     this.setContents("scrollVL width: "                + scrollVL.width        + " / " + scrollVL.getVisibleWidth()        + "<br/>" +
                                      "paddingVL width: "               + paddingVL.width       + " / " + paddingVL.getVisibleWidth()       + "<br/>" +
                                      "DynamicForm width: "             + myDF.width            + " / " + myDF.getVisibleWidth()            + "<br/>" +
                                      "shortTitle Button width: "       + shortTitle.width      + " / " + shortTitle.getVisibleWidth()      + "<br/>" +
                                      "clipItemTitles Button width: "   + clipItemTitles.width  + " / " + clipItemTitles.getVisibleWidth()  + "<br/>" +
                                      "layoutSpacer width: "            + layoutSpacer.width    + " / " + layoutSpacer.getVisibleWidth()    + "<br/>" +
                                      "layoutSpacer2 width: "           + layoutSpacer2.width   + " / " + layoutSpacer2.getVisibleWidth()   + "<br/>" + "<br/>" +
                                      "scrollVL height: "               + scrollVL.height       + " / " + scrollVL.getVisibleHeight()       + "<br/>" +
                                      "paddingVL height: "              + paddingVL.height      + " / " + paddingVL.getVisibleHeight()      + "<br/>" +
                                      "DynamicForm height: "            + myDF.height           + " / " + myDF.getVisibleHeight()           + "<br/>" +
                                      "shortTitle Button height: "      + shortTitle.height     + " / " + shortTitle.getVisibleHeight()     + "<br/>" +
                                      "clipItemTitles Button height: "  + clipItemTitles.height + " / " + clipItemTitles.getVisibleHeight() + "<br/>" +
                                      "layoutSpacer height: "           + layoutSpacer.height   + " / " + layoutSpacer.getVisibleHeight()   + "<br/>" +
                                      "layoutSpacer2 height: "          + layoutSpacer2.height  + " / " + layoutSpacer2.getVisibleHeight()  + "<br/>" +
                                      Math.random());
                  }
              });
              
              isc.LayoutSpacer.create({
                  ID: "layoutSpacer",
                  height: "100%",
              });
              
              isc.LayoutSpacer.create({
                  ID: "layoutSpacer2",
                  height: "100%",
              });
              
              isc.VLayout.create({
                  ID: "outerVL",
                  members: [scrollVL, buttonsLayout, buttonsLayout2, widthsLabel, layoutSpacer, layoutSpacer2],
                  membersMargin: 10,
                  backgroundColor: "#aaa",
                  padding: 5,
                  height: "100%",
                  width: "100%"
              });
              widthsLabel.update();

              Comment


                #8
                Sorry, we've run the code and read your question several times, and we don't understand how you want this to look. Please try explaining again, or perhaps mock up the intended appearance.

                Comment


                  #9
                  Hi Isomorphic,

                  of course. See the mockups created by manually setting heights on scrollVL until it looks as desired:
                  Click image for larger version

Name:	Desired look.png
Views:	101
Size:	135.9 KB
ID:	262282

                  Thank you & Best regards
                  Blama
                  Attached Files

                  Comment


                    #10
                    So you are trying to autofit vertically but scroll horizontally as needed. The way to do this, in this contrived example, would be to start as overflow:"visible" to get auto-fitting and call setOverflow("auto") if you exceed the horizontal space of some container.

                    But this is a contrived example because this isn't how a real screen would be designed. Generally you would leave your forms as overflow:"visible" and place them inside of some scrollable container, but the scrollable container's size is determined by the amount of screen space available.

                    For example, you might have multiple forms, some buttons and some other controls on the screen, maybe all in a tab. The tab would generally be set up to fill the screen, and it scrolls as needed, and that's it - everything just works. You never end up with a need to make a scrolling container also auto-fit to the content. If you did that, you'd generally end up with a bunch of awkwardly separately h-scrolling regions.

                    Finally, just to reiterate: this is pretty much the worse possible handling of long i18n titles - pushing everything off the screen to accommodate one long title. As we covered before, you generally would not expect someone to create such a spectacularly long title, and would want to correct the title if someone did so. And even if you wanted to accommodate bad titles, the best approach would be clipItemTitles, not h-scrolling.

                    Comment


                      #11
                      Hi Isomorphic,

                      thank you for explaining.
                      Yes, this last example was contrived and just for the sake of understanding what it possible out of the box and what will need handlers.
                      I agree that multiple controls with own horizontal scrollbars would look strange.

                      With respect to the i18n titles I agree. Make it as wide as you want so that it fits one language + some buffer and either allow title wrap or clip them.

                      Best regards
                      Blama

                      Comment

                      Working...
                      X