Open EwanOpie opened 1 year ago
Hey @EwanOpie! Thanks so much for the kind words. I can definitely add it to the wishlist as that has came up once or twice. I mostly need to conceptualize how that gets defined by the user. Do you have any ideas? Folder suffix or something?
Eg. "My Dynamo Folder 1.split" would result in split buttons.
I think a suffix would work well and keep thing self-explanetory for users. Keeping the naming aligned with the API definitions could be a good way to do this.
E.g. FolderName.SplitButtons FolderName.StackedButtons
Do you think a fail-safe should be included if a user specifies more than 3 dyn's in a FolderName.StackedButtons folder ( I think that was Revit's maximum ), that it defaults to use FolderName.SplitButton settings? Would at least keep functionality while giving the user an indication there is something not quite correct?
For what Relay provides, I don't think any other styles of panel items would be required, as any kind of additional inputs required by the user should be coded into the dyn's (E.g. Winform's or Dialogs)
I might try and find some time to load all the references into VS to try this 😅, probably not as simple as that though...
EDIT: This worked a treat, not using folder suffix for now as my use case is purely testing, and something wasn't quite working with the 'Sync' function, so I temporarily disabled it. Will grab some feedback from my testing group 👍
@johnpierson Just a comment, when implementing the SplitButtons, there are some timing considerations for when / how the Globals.GraphToRun gets updated. Specifically as to wait for the ComponentManagerOnUIElementActivated to complete fully and return the new "Current" item. Revit seemed to want to do things to quickly, running the Dynamo graph last selected before the new one was registered as the new Global.
I had to Invoke some Delegates and use a ManualResetEvent to get this to work, with a stop-gap of writing an external "GraphToRun" file as the condition to then continue with the cmd execution. I also had to use a different variable to access which button was 'selected',
var adskType = e.UiElement.GetType();
PropertyInfo adskProp = adskType.GetProperty("CommandParameter");
object cmdItem = adskProp.GetValue(e.UiElement);
Process
I hope some of that helps when you get a chance to look at things.
Within the RibbonUtils.AddItems method you add a way to tell if a button is to be stackable, then this is added to a stackable button model in a similar way to the following:
StackableButtonModel:
Once you have a list of stackable buttons, you could utilise the following logic to happen after the main set of ribbon has been completed.
if (Globals.StackAbleButtons.Count > 0)
{
foreach ( Model.StackableButtonModel stackableButton in Globals.StackAbleButtons)
{
int pushButtonDataCount = stackableButton.PushButtonList.Count;
if (pushButtonDataCount == 1)
{
stackableButton.RevitPanel.AddItem(stackableButton.PushButtonList.FirstOrDefault());
}
else if (pushButtonDataCount > 2)
{
if (pushButtonDataCount == 2)
{
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[0], stackableButton.PushButtonList[1]);
Autodesk.Windows.RibbonItem tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[0].Name);
Autodesk.Windows.RibbonItem tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[1].Name);
tempbutton1.ShowText = false;
tempbutton1.Size = RibbonItemSize.Large;
tempbutton2.ShowText = false;
tempbutton2.Size = RibbonItemSize.Large;
}
else if (pushButtonDataCount == 4)
{
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[0], stackableButton.PushButtonList[1]);
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[2], stackableButton.PushButtonList[3]);
Autodesk.Windows.RibbonItem tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[0].Name);
Autodesk.Windows.RibbonItem tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[1].Name);
Autodesk.Windows.RibbonItem tempbutton3 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[2].Name);
Autodesk.Windows.RibbonItem tempbutton4 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[3].Name);
tempbutton1.ShowText = false;
tempbutton1.Size = RibbonItemSize.Large;
tempbutton2.ShowText = false;
tempbutton2.Size = RibbonItemSize.Large;
tempbutton3.ShowText = false;
tempbutton3.Size = RibbonItemSize.Large;
tempbutton4.ShowText = false;
tempbutton4.Size = RibbonItemSize.Large;
}
else if (pushButtonDataCount == 3)
{
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[0], stackableButton.PushButtonList[1],stackableButton.PushButtonList[2]);
}
else
{
int numBoxes = pushButtonDataCount / 3;
int remainder = pushButtonDataCount % 3;
if (remainder == 0)
{
int i = 0;
while (i < numBoxes)
{
List<int> stackCountList = Enumerable.Range(i * 3, 3).ToList();
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[stackCountList[0]], stackableButton.PushButtonList[stackCountList[1]], stackableButton.PushButtonList[stackCountList[2]]);
Autodesk.Windows.RibbonItem tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[0]].Name);
Autodesk.Windows.RibbonItem tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[1]].Name);
Autodesk.Windows.RibbonItem tempbutton3 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[2]].Name);
tempbutton1.ShowText = false;
tempbutton2.ShowText = false;
tempbutton3.ShowText = false;
i++;
}
}
else if (remainder == 2)
{
Autodesk.Windows.RibbonItem tempbutton1;
Autodesk.Windows.RibbonItem tempbutton2;
Autodesk.Windows.RibbonItem tempbutton3;
int i = 0;
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[pushButtonDataCount - 2], stackableButton.PushButtonList[pushButtonDataCount - 1]);
tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 2].Name);
tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 1].Name);
tempbutton1.ShowText = false;
tempbutton1.Size = RibbonItemSize.Large;
tempbutton2.ShowText = false;
tempbutton2.Size = RibbonItemSize.Large;
while (i < numBoxes)
{
List<int> stackCountList = Enumerable.Range(i * 3, 3).ToList();
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[stackCountList[0]], stackableButton.PushButtonList[stackCountList[1]], stackableButton.PushButtonList[stackCountList[2]]);
tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[0]].Name);
tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[1]].Name);
tempbutton3 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[2]].Name);
tempbutton1.ShowText = false;
tempbutton2.ShowText = false;
tempbutton3.ShowText = false;
i++;
}
}
else
{
Autodesk.Windows.RibbonItem tempbutton1;
Autodesk.Windows.RibbonItem tempbutton2;
Autodesk.Windows.RibbonItem tempbutton3;
Autodesk.Windows.RibbonItem tempbutton4;
int i = 0;
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[pushButtonDataCount - 4], stackableButton.PushButtonList[pushButtonDataCount - 3]);
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[pushButtonDataCount - 2], stackableButton.PushButtonList[pushButtonDataCount - 1]);
tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 4].Name);
tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 3].Name);
tempbutton3 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 2].Name);
tempbutton4 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[pushButtonDataCount - 1].Name);
tempbutton1.ShowText = false;
tempbutton1.Size = RibbonItemSize.Large;
tempbutton2.ShowText = false;
tempbutton2.Size = RibbonItemSize.Large;
tempbutton3.ShowText = false;
tempbutton3.Size = RibbonItemSize.Large;
tempbutton4.ShowText = false;
tempbutton4.Size = RibbonItemSize.Large;
numBoxes = numBoxes - 1;
while (i < numBoxes)
{
List<int> stackCountList = Enumerable.Range(i * 3, 3).ToList();
stackableButton.RevitPanel.AddStackedItems(stackableButton.PushButtonList[stackCountList[0]], stackableButton.PushButtonList[stackCountList[1]], stackableButton.PushButtonList[stackCountList[2]]);
tempbutton1 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[0]].Name);
tempbutton2 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[1]].Name);
tempbutton3 = RibbonUtils.GetButton(stackableButton.TabName, stackableButton.Name, stackableButton.PushButtonList[stackCountList[2]].Name);
tempbutton1.ShowText = false;
tempbutton2.ShowText = false;
tempbutton3.ShowText = false;
i++;
}
}
}
}
}
}
@EwanOpie How did you get around the common bug when using FileSystemWatcher because it does sometimes fire two change events off.
I don't think I have experienced that particular bug @brencass . Can you post an example log?
So far my implementation has been performing well, the only minor item being users need to select the tool from the drop-down but run it using the top button once it has been selected.
@EwanOpie Maybe revit is stopping a secondary load of dynamo, so it is not becoming apparent. I have noticed in a test i did that the event that fires up was loading twice when data was saved to a specific file the FileSystemWatcher was watching.
It seems to be a known bug - https://stackoverflow.com/a/1765094
Hi @johnpierson Firstly, wicked tool! Going to be heaps of fun to use.
Secondly, I see that when there is more than 1 dyn in a folder ( Tab section ) that they are inserted in a stack of 2.
Would a slight tweak be possible to allow for when there are more than 2 dyns in a folder a SplitButtongroup is created that allows the usual dropdown selection for Revit toolbar items?