Examples
Inserting User Interfaces into Existing Computer Code
Place an area of code into tabs
We started out by putting a tab view inside a conventional code editor, to provide better interaction with an area of code-- in this case a group of functions that we want sitting next to each other. The tabs below are activated with the cursor's hover instead of click so that the code can be browsed quickly.
// A group of event functions turned into tabs:
{
// do a hit test to see if shapes have been hit.
var didHitAShape = hitTestOnPage();
mouseDown = true;
}{
// drag any shapes being dragged.
if(mouseDown)
{
}
if(shapesAreBeingDragged)
{
}
}{
// reset the mouse down to detect dragging.
mouseDown = false;
}{
// send the keydown event to the KeyboardEventSupervisor.
KeyboardEventSupervisor(event);
}{
// send the keyup event to the KeyboardEventSupervisor.
KeyboardEventSupervisor(event);
}
For the information of what should be in a tab view, there would be an additional file (.interfaces) to go with each code file. Here it lists off what elements are included in a tab view:
tabview{ mouseDown(), mouseUp(), keyDown(), keyUp() }
Alternatively, the section of code would have // --TABS_BEGIN AND // -- TABS_END
Multicolumn Code
// Two columns of functions:
func makeRectangle()
{
// try editing here.
}
func makeCircle()
{
// try editing here.
}
func emptyArray()
{
// try editing here.
}
func moveShape()
{
// try editing here.
}
Grids for Variables, Includes
// A group of related array variables placed into a three-column grid.
var arrayOfRectangles = [];
var arrayOfCircles = [];
var arrayOfTriangles = [];
var arrayOfPentagons = [];
var arrayOfHexagons = [];
var arrayOfSeptagons = [];
var arrayOfOctagons = [];
var arrayOfNonagons = [];
var arrayOfDecagons = [];
Custom Tabs with Custom Labels
Functions can be automatically sorted into tabs like the top example, but for future skimming of your code files, you can set up custom tabs. A document settings window has many user interface controls. They are usually linked to many corresponding variables.
// --TABIFY_START
// --TAB_START:Document Settings Window Variables
var defaultFontSizePt = 14.0;
var documentWidthPt = 612.0;
var documentHeightPt = 792.0;
// --TAB_END
// --TAB_START:Document Settings Window Controls
var fontSizeTextField = TextField();
var widthTextField = TextField();
var heightTextField = TextField();
// --TAB_END
// --TABIFY_END
The result of the custom tab commands above is the tab view below.
// --TABIFY_START
var defaultFontSizePt = 14.0;
var documentWidthPt = 612.0;
var documentHeightPt = 792.0;
var fontSizeTextField = TextField();
var widthTextField = TextField();
var heightTextField = TextField();
// --TABIFY_END
For a future programming system, an additional tab could show the actual interface editor documents for the Document Settings Window. (It would show the window.)
A Viewer for Combining Multiple Interfaces
The first example involved taking a group of functions and assembling them into a tab view. In the second example we showed custom tab views where the programmer made the tabs according to the situation. The third example exhibited multi-column layout for functions and variables.
What we show below is like a photo viewer but for code, specifically the code interfaces you made. You could set it up the way you need.
You can wrap these conventions up into a larger viewer. A viewer interface control allows you to collect all of these multiple interface-based groupings you made and view them in the same place.
In some very long documents, scrolling won't need to take place and editing of all code can be done in this viewer. Multiple viewers could be set up to follow one another in the same file.
In this example we took it a step further and included images that might be included in a program and then interface elements.
The squares on the left activate different pages of interface controls that you already set up.
// --TABIFY_START
var defaultFontSizePt = 14.0;
var documentWidthPt = 612.0;
var documentHeightPt = 792.0;
var fontSizeTextField = TextField();
var widthTextField = TextField();
var heightTextField = TextField();
// --TABIFY_END
{
// do a hit test to see if shapes have been hit.
var didHitAShape = hitTestOnPage();
mouseDown = true;
}{
// drag any shapes being dragged.
if(mouseDown)
{
}
if(shapesAreBeingDragged)
{
}
}{
// reset the mouse down to detect dragging.
mouseDown = false;
}{
// send the keydown event to the KeyboardEventSupervisor.
KeyboardEventSupervisor(event);
}{
// send the keyup event to the KeyboardEventSupervisor.
KeyboardEventSupervisor(event);
} func setup() { // try editing here. } |
func resetAllStates() { // try editing here. } |
func openSelectedEntry() { // try editing here. } |
func addEntry() { // try editing here. } |
func addColumn() { // try editing here. } |
func addRow() { // try editing here. } |
| var numbersArray[] = |
|
| var | states[] | = |
|
./ProjectResources/Images/LandscapeImages/
You could embed several of these viewers into yet a bigger viewer that contains and organizes them in just the same way. This would work fine if expanded to fullscreen on widescreen displays, but this website is limited to 1200px in width.
Zooming map
When provided an interactive demonstration, it is easy to see how an entire code project could be organized in a convenient, zoomable map format. Below is an individual code file comprised of various functions. The functions have been laid out in two columns.
Hover the cursor over the box to zoom into this file, allowing for scrolling.
Moving the cursor outside of the box will shrink the code container back to its thumbnail size. In a code project, there could be multiple thumbnails just like this, shown side by side.
Importantly, it is the multi-column layout of functions that makes this example work, not just the shrinking and expanding of a file's entire contents.
(Note: As this example is completed further, more sections of the code file will be filled in.)
b2CollideCircles
(
manifold: inout b2Manifold,
circleA: b2CircleShape, transformA xfA: b2Transform,
circleB: b2CircleShape, transformB xfB: b2Transform
)
{
manifold.points.removeAll(keepingCapacity: true)
let pA = b2Mul(xfA, circleA.m_p)
let pB = b2Mul(xfB, circleB.m_p)
let d = pB - pA
let distSqr = b2Dot(d, d)
let rA = circleA.m_radius
let rB = circleB.m_radius
let radius = rA + rB
if distSqr > radius * radius {
return
}
manifold.type = b2ManifoldType.circles
manifold.localPoint = circleA.m_p
manifold.localNormal.setZero()
let cp = b2ManifoldPoint()
cp.localPoint = circleB.m_p
cp.id.setZero()
manifold.points.append(cp)
}
b2CollidePolygonAndCircle
(
manifold: inout b2Manifold,
polygonA: b2PolygonShape, transformA xfA: b2Transform,
circleB: b2CircleShape, transformB xfB: b2Transform
)
{
/// Compute the collision manifold between a polygon and a circle.
public func
manifold.points.removeAll(keepingCapacity: true)
// Compute circle position in the frame of the polygon.
let c = b2Mul(xfB, circleB.m_p)
let cLocal = b2MulT(xfA, c)
// Find the min separating edge.
var normalIndex = 0
var separation = -b2_maxFloat
let radius = polygonA.m_radius + circleB.m_radius
let vertexCount = polygonA.m_count
let vertices = polygonA.m_vertices
let normals = polygonA.m_normals
for i in 0 ..< vertexCount {
let s = b2Dot(normals[i], cLocal - vertices[i])
if s > radius {
// Early out.
return
}
if s > separation {
separation = s
normalIndex = i
}
}
// Vertices that subtend the incident face.
let vertIndex1 = normalIndex
let vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0
let v1 = vertices[vertIndex1]
let v2 = vertices[vertIndex2]
// If the center is inside the polygon ...
if separation < b2_epsilon {
manifold.type = b2ManifoldType.faceA
manifold.localNormal = normals[normalIndex]
manifold.localPoint = 0.5 * (v1 + v2)
let cp = b2ManifoldPoint()
cp.localPoint = circleB.m_p
cp.id.setZero()
manifold.points.append(cp)
return
}
// Compute barycentric coordinates
let u1 = b2Dot(cLocal - v1, v2 - v1)
let u2 = b2Dot(cLocal - v2, v1 - v2)
if u1 <= 0.0 {
if b2DistanceSquared(cLocal, v1) > radius * radius {
return
}
manifold.type = b2ManifoldType.faceA
manifold.localNormal = cLocal - v1
manifold.localNormal.normalize()
manifold.localPoint = v1
let cp = b2ManifoldPoint()
cp.localPoint = circleB.m_p
cp.id.setZero()
manifold.points.append(cp)
}
else if u2 <= 0.0 {
if b2DistanceSquared(cLocal, v2) > radius * radius {
return
}
manifold.type = b2ManifoldType.faceA
manifold.localNormal = cLocal - v2
manifold.localNormal.normalize()
manifold.localPoint = v2
let cp = b2ManifoldPoint()
cp.localPoint = circleB.m_p
cp.id.setZero()
manifold.points.append(cp)
}
else {
let faceCenter = 0.5 * (v1 + v2)
let separation = b2Dot(cLocal - faceCenter, normals[vertIndex1])
if separation > radius {
return
}
manifold.type = b2ManifoldType.faceA
manifold.localNormal = normals[vertIndex1]
manifold.localPoint = faceCenter
let cp = b2ManifoldPoint()
cp.localPoint = circleB.m_p
cp.id.setZero()
manifold.points.append(cp)
}
return
}
func b2CollideEdgeAndCircle
(
manifold: inout b2Manifold,
edgeA: b2EdgeShape, transformA xfA: b2Transform,
circleB: b2CircleShape, transformB xfB: b2Transform)
{
manifold.points.removeAll(keepingCapacity: true)
// Compute circle in frame of edge
let Q = b2MulT(xfA, b2Mul(xfB, circleB.m_p))
let A = edgeA.m_vertex1
let B = edgeA.m_vertex2
let e = B - A
// Barycentric coordinates
let u = b2Dot(e, B - Q)
let v = b2Dot(e, Q - A)
let radius = edgeA.m_radius + circleB.m_radius
var cf = b2ContactFeature()
cf.indexB = 0
cf.typeB = b2ContactFeatureType.vertex
// Region A
if v <= 0.0 {
let P = A
let d = Q - P
let dd = b2Dot(d, d)
if dd > radius * radius {
return
}
// Is there an edge connected to A?
if edgeA.m_hasVertex0 {
let A1 = edgeA.m_vertex0
let B1 = A
let e1 = B1 - A1
let u1 = b2Dot(e1, B1 - Q)
// Is the circle in Region AB of the previous edge?
if u1 > 0.0 {
return
}
}
cf.indexA = 0
cf.typeA = b2ContactFeatureType.vertex
manifold.type = b2ManifoldType.circles
manifold.localNormal.setZero()
manifold.localPoint = P
let cp = b2ManifoldPoint()
cp.id.setZero()
cp.id = cf
cp.localPoint = circleB.m_p
manifold.points.append(cp)
return
}
// Region B
if u <= 0.0 {
let P = B
let d = Q - P
let dd = b2Dot(d, d)
if dd > radius * radius {
return
}
// Is there an edge connected to B?
if edgeA.m_hasVertex3 {
let B2 = edgeA.m_vertex3
let A2 = B
let e2 = B2 - A2
let v2 = b2Dot(e2, Q - A2)
// Is the circle in Region AB of the next edge?
if v2 > 0.0 {
return
}
}
cf.indexA = 1
cf.typeA = b2ContactFeatureType.vertex
manifold.type = b2ManifoldType.circles
manifold.localNormal.setZero()
manifold.localPoint = P
let cp = b2ManifoldPoint()
cp.id.setZero()
cp.id = cf
cp.localPoint = circleB.m_p
manifold.points.append(cp)
return
}
// Region AB
let den = b2Dot(e, e)
assert(den > 0.0)
let P = (1.0 / den) * (u * A + v * B)
let d = Q - P
let dd = b2Dot(d, d)
if dd > radius * radius {
return
}
var n = b2Vec2(-e.y, e.x)
if b2Dot(n, Q - A) < 0.0 {
n.set(-n.x, -n.y)
}
n.normalize()
cf.indexA = 0
cf.typeA = b2ContactFeatureType.face
manifold.type = b2ManifoldType.faceA
manifold.localNormal = n
manifold.localPoint = A
let cp = b2ManifoldPoint()
cp.id.setZero()
cp.id = cf
cp.localPoint = circleB.m_p
manifold.points.append(cp)
return
}
