-
Notifications
You must be signed in to change notification settings - Fork 15
Freeform Panel Widget
- Creating a Freeform Panel
- Merging - Reversing a Split
- Adding and Removing Widgets and Views
- Widget/View Alignment
- Utility Methods
- Configuration Options and Instantiation
The Freeform Panel widget is part of the panel widget cluster. The purpose of the freeform panel is to allow a number of arbitrary widgets to be placed into a single display panel. The freeform panel can be split multiple times to create multiple panes, enabling complex visual layouts of widgets and views.
An example of a freeform panel is the Telemetry Panel Widget. The panel is split into multiple sections for displaying multiple widgets together. Then entire panel can be positioned as needed on screen, removing the need for laying out every individual widget's location.
Freeform Panel Widget can be used as a standalone widget or subclassed. It supports a titlebar and close box. (See Titlebar Configuration).
The freeform panel is created with a single pane (accessed via method rootPane
.) Each pane has a PaneID
unique to the panel for identification and manipulation purposes. Panes can be split and merged together dynamically to create complex interfaces. Each pane may contain one DUXBetaBaseWidget
or UIView
type object. Those widgets can be composed of other widgets or views. The content of each pane can be positioned in one of 9 ways, corner, edge, or centered.
Panes can be split either horizontally (along the horizontal axis) or vertically (along the vertical axis). When a split is done, an array of PaneID
is returned to the splitting code.
This example shows splitting horizontally into 5%, 90%, and 5% sections, then dividing the 90% section in two even sections vertically.
let panelWidget = DUXBetaFreeformPanelWidget()
_ = panelWidget.configure(DUXBetaPanelWidgetConfiguration(type: .freeform, variant: .freeform)
.configureTitlebar(visible: true, withCloseBox: true, withBackButton: false,
title: "Freeform Sample", titleHeight: 32.0, titleAlignment: .center))
panelWidget.install(in: self)
panelWidget.enablePaneDebug(assist: true, backgroundAssist: false, textColor: .white, textBackground: .black)
let first3 = panelWidget.splitPane(pane: panelWidget.rootPane(), along: .horizontal, proportions: [0.05, 0.90, 0.05])
let secondSplit = panelWidget.splitPane(pane: first3[1], along: .vertical, proportions: [0.5, 0.5])
var backgroundView = panelWidget.paneView(forPane: secondSplit[0])
backgroundView?.backgroundColor = .blue
backgroundView = panelWidget.paneView(forPane: secondSplit[1])
backgroundView?.backgroundColor = .gray
DUXBetaFreeformPanelWidget *panelWidget = [[DUXBetaFreeformPanelWidget alloc] init];
DUXBetaPanelWidgetConfiguration *config = [[DUXBetaPanelWidgetConfiguration alloc] initWithType:DUXBetaPanelTypeFreeform variant:DUXBetaPanelVariantFreeform];
[config configureTitlebarWithVisible:YES withCloseBox:YES withBackButton:NO title:@"Freeform Sample"
titleHeight:32.0 titleAlignment:DUXBetaPanelTitleBarAlignmentCenter];
[panelWidget installInViewController:self];
[panelWidget enablePaneDebugWithAssist:YES backgroundAssist:NO textColor:UIColor.whiteColor textBackground:UIColor.blackColor];
NSArray<NSNumber*> *first3 = [panelWidget splitPaneWithPane: [panelWidget rootPane] along: DUXBetaFreeformPanelSplitTypeHorizontal proportions: @[@(0.05), @(0.90), @(0.05)]];
NSArray<NSNumber*> *secondSplit = [panelWidget splitPaneWithPane: [first3[1] intValue] along: DUXBetaFreeformPanelSplitTypeVertical proportions: @[@(0.5), @(0.5)]];
UIView *backgroundView = [panelWidget paneViewForPane:secondSplit[0].integerValue];
backgroundView.backgroundColor = UIColor.blueColor;
backgroundView = panelWidget paneViewForPane:secondSplit[1].integerValue];
backgroundView.backgroundColor = UIColor.grayColor;
The code above creates a freeform panel and configures it with a visible toolbar with a close box and title. The first splitPane
calls .rootPane()
for the initial pane to split. Then the second splitPane
splits the second of the 3 panes (the 90% pane) into two panes of 50% and 50%.
The splitPane
call returns an array of the PaneIDs
created for the new panes.
The enablePaneDebug
call is used to turn on the pane debugging assist to show the PaneID
for each pane, but not show background pseudo randomized background colors. To turn off the debugging information:
panelWidget.enablePaneDebug(assist: false, backgroundAssist: false)
[panelWidget enablePaneDebugAssist:NO backgroundAsist:NO];
No autolayout positioning is shown.
Debugging utilities are included in the DUXBetaFreefromPanelWidget
to allow easy debugging of panel layouts via labels and background coloring.
Pane splitting is done by specifying which pane to split, and an array of percentage values to use for the split.
To recombine a split, call mergeChildren
passing in the original PaneID
which was split, or more conveniently, mergeSiblings
, passing any of the sibling PaneIDs
from the split. When mergeSiblings
is called, the PaneID
of the combined siblings is returned.
panel.mergeChildren(parentPane: parentPaneID)
let parentPaneID = panel.mergeSiblings(pane: aSiblingPaneID)
[panel mergeChildrenParentPane:parentPaneID];
PaneID parentPaneID = [panel mergeSiblingsPane:aSiblingPaneID];
During a split or merge, any widgets or views which were added to a pane will be removed.
There are two primary ways to add a widget into a pane, and one way to add a view. You can call the standard extension used to add a widget into a UIViewController
. There has been an extension added to allow that syntax to work with the free from panel.
When adding widgets and view, you can also add margins around the widget or view (optional in Swift)
widget.install(in: panel, pane: targetPaneID, position: .centered)
/* or add custom margins */
widget.install(in: panel, pane: targetPaneID, position: .centered, margins: UIEdgeInsets(top: 4.0, left: 4.0, bottom: 4.0, right: 4.0))
[widget installIn:panel pane:targetPaneID position:DUXBetaFreformPanelWidgetAlignmentCentered margins:UIEdgeInsetsZero];
/* or add custom margins */
[widget installIn:panel pane:targetPaneID position:DUXBetaFreformPanelWidgetAlignmentCentered margins:UIEdgeInsetsMake(4.0, 4.0, 4.0, 4.0)];
The other ways to add a widget or a view into a pane once it has been split off is simply a matter of calling addWidget
or addView
. The two calls are parallel, taking either a widget or view, and the destination PaneID, and the positioning of the widget or view within the pane.
To remove widgets or views, simple call removeWidgetFromPane
or removeViewFromPane
.
panel.addWidget(widget: newWidget, toPane: destinationWidgetPane, position: .centered)
panel.addWView(view: newWidget, toPane: desinationViewPane, position: .top, margins: UIEdgeInsets(top: 4.0, left: 4.0, bottom: 4.0, right: 4.0))
pane.removeWidgetFromPane(pane: desinationWidgetPane)
pane.removeViewFromPane(pane: desinationViewPane)
[pane addWidget:newWidget toPane: desinationWidgetPane position: DUXBetaFreformPanelWidgetAlignmentCentered margins: UIEdgeInsetsZero];
[pane addView:newView toPane: desinationViewPane position: DUXBetaFreformPanelWidgetAlignmentTop margins:UIEdgeInsetsZero];
[panel.removeWidgetFromPane:destinationWidgetPane];
[panel.removeViewFromPane:desinationViewPane];
Widgets and views are positioned when they are added using the position parameter. There are 9 defined positions which can be used.
For Objective-C the base of each constant is DUXBetaFreeformPanelWidgetAlignment
.
centered
topLeading
top
topTrailing
leading
trailing
bottomLeading
bottom
bottomTrailing
Positioning can also be changed dynamically by using
panel.setPositioning(myPaneID, positioning: .bottomTrailing, margins: UIEdgeInsets.zero);
[panel setPositioning(myPaneID positioning: DUXBetaFreformPanelWidgetAlignment margins:UIEdgeInsetsZero];
Several utility methods have been provided to make manipulation of freeform panels easier and more convenient.
-
findPaneWithWidget
- Takes a widget as an argument and returns thePaneID
containing the widget or -1 if not found. -
widgetInPane
- Takes aPaneID
as an argument and returns the widget installed in the pane or nil if pane contains a view or no widget. -
viewInPane
- Takes aPaneID
as an argument and returns the view installed in the pane or nil if pane contains a widget or no view. -
getSiblingsList
- Take aPaneID
as an argument and returns an inclusive list of all siblings. -
getParentID
- Takes aPaneID
as an argument and returns the parent PaneID or -1 if thePaneID
is the root pane. -
backgroundViewForPane
- Takes aPaneID
as an argument and returns the background view used in the pane. -
setBackgroundColor
- Takes a UIColor or nil, and aPaneID
and sets the background color for the pane. Passnil
for the color to make a transparent background. -
paneID(forView:)
- Take a view and returns thePaneID
containing the view or -1 if not found.
When creating a DUXBetaFreeformPanelWidget
, the configuration object specifies the widget type (DUXBetaPanelType = .freeform
) and variant (DUXBetaPanelVariant = .freeform
).
Other configuration options are described in Panel Configuration.
DJI UX SDK Version 5 Beta 4.1