Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Bad ribbon bar stuff that doesn't match MS Word Collapse All
Subject Author Date
Robert Webb Mar 21, 2010 - 8:35 PM

Some observations about ribbon bar layouts.  These are things that stand out as poor uses of space, and don’t seem to happen with MS Word:


It seems as the ribbon bar is reduced in size and groups collapse to single buttons, that it is not possible for a group to collapse to a single button without all subsequent groups doing the same (all groups to the right of it).  This is not how MS Word does it.  If a large group is collapsed, then subsequent groups may stay expanded if there’s room.  Eg the View tab in MS Word.  Shrink the window until the "Show/Hide" group collapses into a single button.  Subsequent groups all stay full size.


MS Word is also able to reduce some buttons from large to small within a group without having to reduce all of them as Prof-UIS does.  Eg if there are 5 or 6 buttons, MS Word will first shrink the last 3 to small, leaving the first 2 or 3 large.  Prof-UIS always collapses all at once, even when there are separators within the group.


MS Word also appears to NEVER collapse a group to a single button if it would not lead to a saving of space.  Eg a group with a single button and not-too-long text.


Similarly, there is no point reducing buttons from large with text below to small with text at the side unless it will save space.  I’ve seen Prof-UIS make that adjustment even though it results in the group being larger!  That is, since the text is now beside the icon rather than below it, you may end up with a wider group even though the button icon has shrunk (also because text that was over two lines below a large icon becomes text in a single line, making it longer).  This also seems to be avoided in MS Word.


I’m pretty sure BCG and CodeJock handle these things correctly.


Thanks,


Rob.

Technical Support Apr 5, 2010 - 5:20 AM

We can modify the RibbonBar sample application for you. Please choose some ribbon tab page and tell us which buttons should collapse in some specific order. We will modify this sample application for you by coding the button behavior rules you need.

Robert Webb Apr 6, 2010 - 2:06 AM

Thanks.  Looks like the Page Layout --> Arrange group would be a good one.  It has seven buttons.  Let’s number them 1 through 7 from left to right.  As the window is made smaller, here’s the order of what should happen:


(1) All buttons start off big.


(2) Last 3 buttons (5,6,7) are made small with text.


(3) Buttons 2,3,4 are also made small with text.


(4) Buttons 5,6,7 are made small without text.


(5) Buttons 2,3,4 are also made small without text.


(6) Whole group is collapsed to a single button.


Currently we see steps 1, 3, 4, and 6.  That is, all the last six buttons collapse at once from large to small with text (skipping step 2).  And the whole group collapses to a single button before buttons 2,3,4 are shrunk from small with text to small without text.


I still suggest that the above sequence should happen automatically for any collection of buttons with equal priority rules, and I believe this is how other ribbon bars behave, ie the developer does not have to write special code to make it happen.  I will be wanting to automate it for all our controls.  Hopefully I will be able to do that based on your changes to the ribbon sample code.


Thanks,


Rob.

Robert Webb Apr 13, 2010 - 7:19 PM

How’s this going?  Let me know if anything wasn’t clear in my explanation.


Thanks,


Rob.

Technical Support Apr 15, 2010 - 2:10 PM

We are sorry for the delay with this answer. Please update the source code for the CMainFrame::_InitRibbonNode_PageLayout_Arrange() method in the RibbonBar sample application:

CExtRibbonNode * CMainFrame::_InitRibbonNode_PageLayout_Arrange()
{
CExtRibbonNodeGroup * pRibbonGroup =
                        new CExtRibbonNodeGroup( ID_RIBBON_PAGE_PL_ARRANGE );
            pRibbonGroup->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("ZA") ) ), false );
                                    {           // block: coding rules
                                                pRibbonGroup->RibbonILE_SetCollapsed( __EXT_RIBBON_ILE_MIN );
                                    }           // block: coding rules
            VERIFY( pRibbonGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_LARGE) ) );
            pRibbonGroup->m_iconBig.m_bmpNormal.Make32();
            pRibbonGroup->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pRibbonGroup->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_SMALL) ) );
            pRibbonGroup->m_iconSmall.m_bmpNormal.Make32();
            pRibbonGroup->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->SetTextInToolbar( _T("Arrange") );

CExtRibbonNodeDialogLauncher * pRibbonDLB =
                        new CExtRibbonNodeDialogLauncher( ID_RIBBON_PAGE_PL_ARRANGE );
            pRibbonDLB->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("PA") ) ), false );
            pRibbonGroup->InsertNode( NULL, pRibbonDLB );


            //////////////////// 1 ////////////////////

CExtRibbonNode * pNodePositionBox =
                        new CExtRibbonNode( ID_ARRANGE_POSITION_LARGE, 0, NULL, 0, _T("Position") );
            pNodePositionBox->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("PO") ) ), false );
            pNodePositionBox->RibbonILE_RuleRemoveSmallILV();
            pNodePositionBox->RibbonILE_RuleRemoveNormalILV();
            VERIFY( pNodePositionBox->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_POSITION_LARGE) ) );
            pNodePositionBox->m_iconBig.m_bmpNormal.Make32();
            pNodePositionBox->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodePositionBox
                        );


            //////////////////// 2, 3, 4 ////////////////////

CExtRibbonNode * pNodeBringToFront =
                        new CExtRibbonNode( ID_ARRANGE_BTF_LARGE, 0, NULL, 0, _T("Bring to\nFront") );
            pNodeBringToFront->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AF") ) ), false );
//          pNodeBringToFront->RibbonILE_RuleRemoveSmallILV();
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeBringToFront->RibbonILE_RuleArrayGeta();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            VERIFY( pNodeBringToFront->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_LARGE) ) );
            pNodeBringToFront->m_iconBig.m_bmpNormal.Make32();
            pNodeBringToFront->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeBringToFront->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_BTF_SMALL) ) );
            pNodeBringToFront->m_iconSmall.m_bmpNormal.Make32();
            pNodeBringToFront->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeBringToFront
                        );

CExtRibbonNode * pNodeSendToBack =
                        new CExtRibbonNode( ID_ARRANGE_STB_LARGE, 0, NULL, 0, _T("Send to\nBack") );
            pNodeSendToBack->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AE") ) ), false );
//          pNodeSendToBack->RibbonILE_RuleRemoveSmallILV();
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeSendToBack->RibbonILE_RuleArrayGet();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            VERIFY( pNodeSendToBack->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_STB_LARGE) ) );
            pNodeSendToBack->m_iconBig.m_bmpNormal.Make32();
            pNodeSendToBack->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeSendToBack->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_STB_SMALL) ) );
            pNodeSendToBack->m_iconSmall.m_bmpNormal.Make32();
            pNodeSendToBack->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeSendToBack
                        );

CExtRibbonNode * pNodeTextWrapping =
                        new CExtRibbonNode( ID_ARRANGE_TW_LARGE, 0, NULL, 0, _T("Text\nWrapping") );
            pNodeTextWrapping->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("TW") ) ), false );
//          pNodeTextWrapping->RibbonILE_RuleRemoveSmallILV();
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeTextWrapping->RibbonILE_RuleArrayGet();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-2, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-4, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            VERIFY( pNodeTextWrapping->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_TW_LARGE) ) );
            pNodeTextWrapping->m_iconBig.m_bmpNormal.Make32();
            pNodeTextWrapping->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeTextWrapping->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_TW_SMALL) ) );
            pNodeTextWrapping->m_iconSmall.m_bmpNormal.Make32();
            pNodeTextWrapping->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeTextWrapping
                        );

            //////////////////// 5, 6, 7 ////////////////////

CExtRibbonNode * pNodeAlign =
                        new CExtRibbonNode( ID_ARRANGE_ALIGN_LARGE, 0, NULL, 0, _T("Align") );
            pNodeAlign->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AA") ) ), false );
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeAlign->RibbonILE_RuleArrayGet();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            VERIFY( pNodeAlign->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ALIGN_LARGE) ) );
            pNodeAlign->m_iconBig.m_bmpNormal.Make32();
            pNodeAlign->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeAlign->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ALIGN_SMALL) ) );
            pNodeAlign->m_iconSmall.m_bmpNormal.Make32();
            pNodeAlign->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeAlign
                        );

CExtRibbonNode * pNodeGroup =
                        new CExtRibbonNode( ID_ARRANGE_GROUP_LARGE, 0, NULL, 0, _T("Group") );
            VERIFY( pNodeGroup->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_GROUP_LARGE) ) );
            pNodeGroup->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AG") ) ), false );
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeGroup->RibbonILE_RuleArrayGet();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            pNodeGroup->m_iconBig.m_bmpNormal.Make32();
            pNodeGroup->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeGroup->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_GROUP_SMALL) ) );
            pNodeGroup->m_iconSmall.m_bmpNormal.Make32();
            pNodeGroup->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeGroup
                        );

CExtRibbonNode * pNodeRotate =
                        new CExtRibbonNode( ID_ARRANGE_ROTATE_LARGE, 0, NULL, 0, _T("Rotate") );
            pNodeRotate->CmdKeyTipSet( new CExtCustomizeCmdKeyTip( __EXT_MFC_SAFE_LPCTSTR( _T("AY") ) ), false );
                                    {           // block: coding rules
                                                CArray < DWORD, DWORD > & arrRules = pNodeRotate->RibbonILE_RuleArrayGet();
                                                arrRules.RemoveAll();
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-0, __EXT_RIBBON_ILV_SIMPLE_LARGE,  false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-1, __EXT_RIBBON_ILV_SIMPLE_NORMAL, false ) );
                                                arrRules.Add( __EXT_RIBBON_MAKE_RULE_ARRAY_ENTRY( __EXT_RIBBON_ILE_MAX-3, __EXT_RIBBON_ILV_SIMPLE_SMALL,  false ) );
                                    }           // block: coding rules
            VERIFY( pNodeRotate->m_iconBig.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ROTATE_LARGE) ) );
            pNodeRotate->m_iconBig.m_bmpNormal.Make32();
            pNodeRotate->m_iconBig.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            VERIFY( pNodeRotate->m_iconSmall.m_bmpNormal.LoadBMP_Resource( MAKEINTRESOURCE(ID_ARRANGE_ROTATE_SMALL) ) );
            pNodeRotate->m_iconSmall.m_bmpNormal.Make32();
            pNodeRotate->m_iconSmall.m_bmpNormal.AlphaColor( RGB(255,0,255), RGB(0,0,0), 0 );
            pRibbonGroup->InsertNode(
                        NULL,
                        pNodeRotate
                        );

            return pRibbonGroup;
}

Robert Webb Apr 15, 2010 - 7:51 PM

Ah, thanks, this is very helpful!  I should be able to figure out how to automate it from this.  I still think this kind of section-by-section collapsing should happen by default, even when two items have the same effective level.


One thing I don’t understand.  Why is __EXT_RIBBON_ILE_MAX set to 10?  That puts a pretty small limit on the number of levels available.  It also appears that 5 bits are set aside for this value (__EXT_RIBBON_BIT_COUNT_ILE), so why not allow all 32 levels that could be represented?  That is, set __EXT_RIBBON_ILE_MAX to 31.  And finally, it seems there are 26 bits used for the visual level, but aren’t there typically less visual levels than effective ones?  Just 3 in fact, as far as I know.  Why not give more bits to the effective level?


Thanks,


Rob.

Robert Webb Apr 21, 2010 - 8:27 PM

Any thoughts on this?  I’ve written a function to create nice rules for buttons in ribbon groups, but I ran into the foreseen problem of the very limited number of possible effective levels.  One of our groups has 16 buttons (9 buttons followed by a separator and then another 7).  There are only 11 effective levels available (0 - 10).  The minimum one is used to collapse the whole group to a button.  The maximum one represents all buttons at full size.  This leaves 9 levels (1 - 9).  Half are required for dropping from full size to normal, and half are required to drop from normal to small, so really only 4 groupings of buttons can have different levels.  Grouping 3 at a time (3 buttons appear in a column and should collapse together), and taking note of the separator, our above ribbon group requires 6 groupings.


So I ask again, why is __EXT_RIBBON_ILE_MAX set to 10 when there are enough bits set aside for 32 levels? Why are more bits set aside for visual levels, even though visual levels are accessed via effective levels so there’s never a need for more visual levels than effective levels.


Is there a reason not to just change __EXT_RIBBON_BIT_COUNT_ILE from 5 to 16 and __EXT_RIBBON_ILE_MAX from 10 to 65535?  (Or better, (1 << __EXT_RIBBON_BIT_COUNT_ILE) - 1).


Thanks,


Rob.

Technical Support Mar 22, 2010 - 11:38 AM

Sorry but we do not agree. Everything can be coded using ribbon command node rules. You can change visual informativeness (small - small 16x16 icon only, middle - small 16x16 icon and text at right, big - large 32x32 icon and 1 or 2 lines of text at bottom) of any node anytime. It’s possible to change visual informativeness of buttons at left earlier than buttons at right in the same or different ribbon groups. Everything is defined by effective informativeness level to visual informativeness level pair of numbers. Each node supports array of such pairs. If the ribbon bar width is changed, then it tries to find the larges effective informativeness level for all the nodes/buttons when all the buttons are visible and does not intersect with the right side if the ribbon bar. But each effective informativeness level of each node/button has corresponding visual level. If the buttons at the left side still use the big visual level at a smaller effective level, then the buttons at left kept larger then buttons at right. The same rules applied to the button groups. But the button groups also support the collapsed state which is linked to effective informativeness level. This means you can collapse button groups at left later than button groups at right or vice versa. Of course, you can avoid group collapsing at all what is really recommended for button groups containing one always big button or three always small/middle buttons.

Robert Webb Mar 22, 2010 - 11:40 PM

Is there any documentation or sample code related to these ribbon bar rules?  I can’t find any.  The documentation has a brief page about RibbonILE_RuleArrayGet(), but it really doesn’t explain what it does.  It returns an array of integers.  By default they seem to be "73, 40, 7".  The only way to make any sense of these is to look inside the Prof-UIS code.  Seems the bottom 5 bits are used as the effective level.  The rest is used for the visible level.  I think it ends up meaning that an effective level of 9 makes it large, a level of 8 leads to normal size, and a level of 7 leads to small icons with no text.  Is that right?


I’m guessing that a single effective level is tried at once for all controls within a group, which is why you can’t shrink some buttons and not others when they have the same rules.


To say that the poor uses of space as I described "can" be coded in Prof-UIS may be true, but only by pushing much of the responsibility back onto us the programmers, and require us to use undocumented features.  The whole point of the ribbon bar, as I see it, is to AUTOMATICALLY come up with nice layouts.  It’s nice if we have the power to tell it that one item is more important than another, and should thus shrink later, but the Prof-UIS solution seems overly convoluted and difficult to use, and doesn’t provide good defaults if the programmer doesn’t want to have to think about how every element should arrange itself.  I think all the things I described above should happen by default, as I believe they do when using other ribbon bar toolkits.


Rob.

Robert Webb Apr 1, 2010 - 1:14 AM

Thoughts?


I still don’t really know how to make buttons within a group shrink three at a time rather than all at once, as seems to happen automatically in other ribbon bar implementations.  There may be a convoluted way by playing with the rules, but there’s no explanation anywhere of how to use these rules.


Rob.