Methods¶
Contains¶
bool Contains(Func<T, bool> condition)
Returns true if the tree contains AT LEAST ONE node that satisfied the condition provided by the lambda function.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male
Id: Dad, Name: Richard Jr, Gender: Male
Id: SisterJane, Name: Jane, Gender: Female
Id: Me, Name: MeMyselfAndI, Gender: Male
Id: UndleJohn, Name: John, Gender: Male
Id: CousinAnn, Name: Ann, Gender: Female
*/
var containsFemale = familyTree.Contains(p => p.Gender == Gender.Female); // true
var containsOnlyChild = familyTree.Contains(p => p.Children.Count == 1); // true
var containsMother = familyTree.Contains(p => p.HasChildren && p.Gender == Gender.Female); // false
DeepCopy¶
T DeepCopy()
Makes a deep copy (clone) of the tree. If this method is called on a node that is in the middle of an existing tree, then a copy of the branch will be returned where the branch node becomes the root object. It works like an unmount in a Linux file system except that the unmounted branch is returned. Another way to look at it is that it functions like the spread operator (…) in Javascript, except that it is a recursive spread.
Warning
DeepCopy() serializes and deserializes the tree in order to create a full copy of every object. If your class contains references to anything that references it back then you will see a circular reference exception. Before calling DeepCopy(), you must ensure that there are no circular referencing properties in your class.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
// Make a copy of the whole tree
var familyTreeCopy = familyTree.DeepCopy();
// Make a copy of a branch
var branchCopy = familyTree.Children[0].DeepCopy();
/*
branchCopy looks like this
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: null
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
*/
Filter¶
T Filter(Func<T, bool> filter)
Returns a pruned tree where only the nodes that match the filter are returned with their complete ancestor paths up to the root. Nodes that are not matched are not included. If a branch of nodes does not have a matching node in it, then the entire branch of nodes will be excluded from the returned tree.
Warning
Filter() uses the DeepCopy() method, which serializes and deserializes the tree in order to create a full copy of the objects it needs to produce the result. If your class contains references to anything that references it back then you will see a circular reference exception. Before calling DeepCopy(), you must ensure that there are no circular referencing properties in your class.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinSteve, Name: Steve, Gender: Male, ParentId: John
Id: UncleLuke, Name: Luke, Gender: Male, ParentId: Grandpa
Id: CousinMary, Name: Mary, Gender: Female, ParentId: UncleLuke
*/
var femaleTree = familyTree.Filter(p => p.Gender === Gender.Female);
/*
femaleTree will look like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: UncleLuke, Name: Luke, Gender: Male, ParentId: Grandpa
Id: CousinMary, Name: Mary, Gender: Female, ParentId: UncleLuke
*/
In the example above note the following:
Grandpa, Dad, and UncleLuke are all included because they have a matching node in their descendants
MeMyselfAndI is not included in the list of Children for Dad because it doesn’t match the filter condition
UndleJohn and its descendants are entirely excluded because there are no matching nodes in that branch
FindById¶
T FindById(TId nodeId)
Finds and returns the T
object where the Id
value is equal to the nodeId
value provided as an argument. It will search the tree recursively until it is found. TId
is
the type of the Id
property.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
var targetNode = familyTree.FindById("UndleJohn");
In the example above note the following:
targetNode
will contain the “UncleJohn” branch in the tree above
targetNode.Parent.Id
is “Grandpa”
targetNode.Children[0].Id
is “CousinAnn”
Find¶
T Find(Func<T, bool> condition)
Finds and returns the object of type T
where the condition
implemented by the lambda function returns
true. It will search the tree recursively until the first item is found ignoring any other nodes that match
the condition
.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
var targetNode = familyTree.Find(p => p.Gender == Gender.Female);
In the example above note the following:
targetNode.Id
is “SisterJane”The node with
Id == "CousinAnn"
also satisfies the filter condition but it is ignored because it will find “SisterJane” first
IsAncestor¶
bool IsAncestor(T treeNode)
Determines if the node provided as the treeNode
is an ancestor of this node up the tree.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
var grandpa familyTree.FindById("Grandpa");
var dad = familyTree.FindById("Dad");
var uncle = familyTree.FindById("UncleJohn");
var me = familyTree.FindById("Me");
bool result;
// result == true
result = me.IsAncestor(grandpa);
// result == true
result = me.IsAncestor(dad);
// result == false
result = me.IsAncestor(uncle);
IsDescendent¶
bool IsDescendent(T treeNode)
Determines if the node provided as the treeNode
is a descendant of this node down the tree
recursively.
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
var grandpa familyTree.FindById("Grandpa");
var dad = familyTree.FindById("Dad");
var uncle = familyTree.FindById("UncleJohn");
var me = familyTree.FindById("Me");
bool result;
// result == true
result = grandpa.IsDescendent(dad);
// result == true
result = grandpa.IsDescendent(me);
// result == false
result = uncle.IsDescendent(me);
IsSibling¶
bool IsSibling(T treeNode)
Determines if the node provided as the treeNode
is a sibling of this node (i.e. they share
the same Parent
and are members of the same Children
collection).
Example:
/*
Given the tree below
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
var dad = familyTree.FindById("Dad");
var uncle = familyTree.FindById("UncleJohn");
var sister = familyTree.FindById("SisterJane");
var me = familyTree.FindById("Me");
var cousin = familyTree.FindById("CousinAnn");
bool result;
// result == true
result = dad.IsSibling(uncle);
// result == true
result = me.IsSibling(sister);
// result == false
result = me.IsSibling(cousin);
MakeChildOfUpperSibling¶
void MakeChildOfUpperSibling()
Makes this node a child of the sibling higher in the order of the Children
collection of its
parent. In a user-interface this method could be wired to a right-arrow that moves the node to
the right in the tree causing it to be indented under the item above it.
Example:
/*
Given the tree below: CousinAnn is misplaced as a child of Grandpa
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var cousin = familyTree.FindById("CousinAnn");
cousin.MakeChildOfUpperSibling();
/*
The tree now looks like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
MakeSiblingOfParent¶
void MakeSiblingOfParent(bool takeLowerSiblingsAsChildren = false)
Makes this node a sibling of its parent. In a user-interface this method could be wired to a
left-arrow that moves the node to the left in the tree causing it to be indented at the same
level of the item above it and thereby converting it into a sibling of its parent. The
takeLowerSiblingsAsChildren
, if true
, will cause any existing siblings under it to
be converted into its children. The default is for the lower siblings to remain children of
the upper (formerly Parent
) item.
Example:
/*
Given the tree below: UndleJohn is misplaced as a child of Dad
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Dad
Id: SisterMary, Name: Mary, Gender: Female, ParentId: Dad
*/
var uncle = familyTree.FindById("UndleJohn");
uncle.MakeSiblingOfParent();
/*
The tree now looks like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: SisterMary, Name: Mary, Gender: Female, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
*/
Note the following in the example above
SisterMary
remains a child ofDad
Example using takeLowerSiblingsAsChildren = true
:
/*
Given the tree below: UndleJohn is misplaced as a child of Dad
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Dad
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Dad
*/
var uncle = familyTree.FindById("UndleJohn");
uncle.MakeSiblingOfParent(true);
/*
The tree now looks like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: John
*/
Note the following in the example above
CousinAnn
becomes a child ofUndleJohn
MoveDownInSiblingOrder¶
void MoveDownInSiblingOrder()
Moves this node down in the sibling order. In a user-interface this method could be wired to a down-arrow causing the node to be moved down in the sibling order. It will stop moving down when it gets to the bottom of the sibling order at its current level in the tree.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var sister = familyTree.FindById("SisterJane");
sister.MoveDownInSiblingOrder();
/*
The tree now looks like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
MoveUpInSiblingOrder¶
void MoveUpInSiblingOrder()
Moves this node up in the sibling order. In a user-interface this method could be wired to an up-arrow causing the node to be moved up in the sibling order. It will stop moving up when it gets to the top of the sibling order at its current level in the tree remaining under its current parent.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var me = familyTree.FindById("Me");
me.MoveUpInSiblingOrder();
/*
The tree now looks like this
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
ProcessTree¶
void ProcessTree(Action<T> nodeProcessor)
Passes each child of this node to the nodeProcessor
recursively down the tree,
where the nodeProcessor
is a lambda function used as the handler. Unlike
ProcessChildren
, this method will start with (include) this node.
void ProcessTree(ITreeNodeProcessor<TId, T> nodeProcessor)
Passes each child of this node to the nodeProcessor
recursively down the tree, where the
nodeProcessor
is a handler object that implements ITreeNodeProcessor<TId, T>
. Unlike
ProcessChildren
, this method will start with (include) this node.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
familyTree.ProcessTree(p => Console.WriteLine(p.IndentString + p.Id));
/*
Output:
Grandpa
Dad
SisterJane
Me
UncleJohn
CousinAnn
*/
Note the following in the example above:
The root node with Id=”Grandpa” is included in the output because processing begins with the calling node itself
To process nodes down the tree excluding the current node use the ProcessChildren() method below
ProcessChildren¶
void ProcessChildren(Action<T> nodeProcessor)
Passes each child of this node to the nodeProcessor
recursively down the tree, where
the nodeProcessor
is a lambda function used as the handler. The method does not include
this node when processing the tree.
void ProcessChildren(ITreeNodeProcessor<TId, T> nodeProcessor)
Passes each child of this node to the nodeProcessor
recursively down the tree, where the
nodeProcessor
is a handler object that implements ITreeNodeProcessor<TId, T>
. The method
does not include this node when processing the tree.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
familyTree.ProcessChildren(p => Console.WriteLine(p.IndentString + p.Id));
/*
Output:
Dad
SisterJane
Me
UncleJohn
CousinAnn
*/
Note the following in the example above:
The root node with Id=”Grandpa” is not in the output because processing begins with the Children
ProcessAncestors¶
Using Lambda with maxLevel Parameter
void ProcessAncestors(
Action<T> nodeProcessor,
T startNode,
int maxLevel = 1
)
Passes each node up the tree of ancestors to the nodeProcessor
function starting with startNode
and stopping at the node where DepthFromRoot
= 1 (i.e. the top) or the specified maxLevel
.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var me = familyTree.FindById("Me");
familyTree.ProcessAncestors(p => Console.WriteLine(p.Id), me);
/*
Output:
Me
Dad
Grandpa
*/
familyTree.ProcessAncestors(p => Console.WriteLine(p.Id), me, 2);
/*
Output:
Me
Dad
*/
Note the following in the example above:
In both calls the starting node is
me
so the Id “Me” is output firstIn the first call to ProcessAncestors() the default
maxLevel = 1
was used, which means that by default it will go all the way to the root node. That is whyGrandpa
is in the outputIn the second call to ProcessAncestors() it uses
maxLevel = 2
, so it stops processing at the ancestor withDepthFromRoot == 2
, which isDad
Using Lambda with Stop Function
void ProcessAncestors(
Action<T> nodeProcessor,
T startNode,
Func<T, bool> stopFunction
)
Passes each node up the tree of ancestors to the nodeProcessor
function starting with
startNode
and stopping at the node that causes the stopFunction to return true.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var me = familyTree.FindById("Me");
familyTree.ProcessAncestors(
nodeProcessor: p => Console.WriteLine(p.Id),
startNode: me,
stopFunction: p => p.Name.Contains("Jr")
);
/*
Output:
Me
Dad
*/
Note the following in the example above:
In both calls the starting node is
me
so the Id “Me” is output firstThe stop function is more complex than a level number
You can make the stop function as sophisticated as is necessary
Using ITreeNodeProcessor Class with maxLevel
void ProcessAncestors(
ITreeNodeProcessor<TId, T> nodeProcessor,
T startNode,
int maxLevel = 1
)
Passes each node up the tree of ancestors to the nodeProcessor
starting with startNode
and stopping at the node where DepthFromRoot
= 1 (i.e. the top) or the specified maxLevel
.
Example:
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
public class MyTreeNodeProcessor : ITreeNodeProcessor<string, Person>
{
public void ProcessNode(Person node) => Console.WriteLine(node.Id);
}
var myNodeProcessor = new MyTreeNodeProcessor();
var me = familyTree.FindById("Me");
familyTree.ProcessAncestors( myNodeProcessor, me );
/*
Output:
Me
Dad
Grandpa
*/
Note the following in the example above:
In both calls the starting node is
me
so the Id “Me” is output firstThe default
maxLevel = 1
was used, which means that by default it will go all the way to the root node, which is whyGrandpa
is in the outputWhile not demonstrated here, when using a class you can also specify an integer
maxLevel
or astopFunction
lambda to make it stop climbing the ancestor tree at the defined level
ToList¶
List<T> ToList()
Returns all nodes in the tree as a flattened collection of type List<T>
sorted by the SortableTreePath
property. If this method is called on a branch then it will return only the nodes in that branch where the top
of the branch is the root and will be the first element in the list.
/*
Given the tree below:
Id: Grandpa, Name: Richard, Gender: Male, ParentId: null
Id: Dad, Name: Richard Jr, Gender: Male, ParentId: Grandpa
Id: SisterJane, Name: Jane, Gender: Female, ParentId: Dad
Id: Me, Name: MeMyselfAndI, Gender: Male, ParentId: Dad
Id: UndleJohn, Name: John, Gender: Male, ParentId: Grandpa
Id: CousinAnn, Name: Ann, Gender: Female, ParentId: Grandpa
*/
var flatList = familyTree.ToList();
flatList.ForEach(p => p.Console.WriteLine(p.SortableTreePath));
/*
Output:
1
1.1
1.1.1
1.1.2
1.2
1.2.1
*/
flatList.ForEach(p => p.Console.WriteLine(p.IndentString + p.Id));
/*
Output:
Grandpa
Dad
SisterJane
Me
UncleJohn
CousinAnn
*/
Note the following in the example above:
The first call above shows how the
SortableTreePath
property can be used to display the tree items in the property order without having to recurse the tree even through the list is flat.The second call above demonstrates the fact that the tree can be displayed in nested fashion using the
IndentString
property without recursing by virtue of the fact that the list is sorted by theSortableTreePath
property.


--- layout: post status: publish published: true title: More on the MacBook Logic Board author: Arthur Rosa author_login: arthurlockman author_email<EMAIL_ADDRESS>author_url: https://b.rthr.me wordpress_id: 791 wordpress_url: http://b.rthr.me/?p=791 date: '2015-03-13 13:30:41 -0400' date_gmt: '2015-03-13 17:30:41 -0400' image: https://static.rthr.me/2015/03/new-macbook-logic-board.jpg tags: - Apple ---
I had some more thoughts on the new MacBook's logic board that didn't fit so well into my post from yesterday. The new tiny low-power logic board from the new MacBook could open up a whole new world of possibilities for a lot of existing Apple products. A Mac Mini powered by the a board of that size that can fit in your pocket for traveling is one1. A next-generation TV with more powerful hardware and a diminutive size. It also opens the possibility for Apple to be able to move more back into the education market with smaller computers that could have a better performance to price ratio, all powered by the small new logic board. ARM-based or not, it could open a whole new world of possibilities.
I think there's also a possibility of some sort of standardization in terms of the logic boards in some of the lower-end Macs. I can see a time in the future where the MacBook 12", the Mac Mini, and the low-end iMac all use the same exact logic board with slightly different processor and memory configurations. Then like with the iPad Air and Mini, and the iPhone 6/s, the choice of which computer to buy really is only about the size2. It makes the choice of which to buy much easier for a lot of people, which I think would be really good.
Who knows, this thing could potentially end up powering the mythical iPad Pro3. I guess we'll just have to wait and see.


Wilson Xie
Role: Working in front end most likely.
Skills: Not much experience with web development other than the 412 lab class. So I only know some html, css, JavaScript. No experience with back-end other than being able to navigate directories.
Goals: Want to learn to be proficient in whatever technologies we use and to be a good teammate.


Introduction
The FreeClimb C# SDK will allow you to easily use the FreeClimb API in a C# application.
SDK Installation
Download and uncompress. You can open the solution file in Visual Studio.
Testing your Installation
Test the SDK is working by sending yourself a phone call.
using com.freeclimb;
using com.freeclimb.api;
using com.freeclimb.api.call;
...
FreeClimbClient client = new FreeClimbClient("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "your_auth_token");
string to = "your_phone_number";
string from = "a_freeclimb_phone_number_in_your_account";
// the last (null) parameter is a URL that is called with status on your call (like when it ends). Not used in this example
Call call = client.getCallsRequester.create(to, from, "https://www.freeclimb.com/testApp/voice", null);
When you run this code you should get a phone call. On answering the call, you should hear a short message ("Thanks for using FreeClimb!"). This indicates that you've successfully setup your SDK.
https://www.freeclimb.com/testApp/voice
contains a small FreeClimb application. When a request is made to its /voice
endpoint, it will respond with the following PerCL script, which produces the message you heard.
[{"Say": {"text": "Thanks for using FreeClimb!"}}]
Documentation
The FreeClimb documentation has guides on getting started with FreeClimb, as well as the API reference and PerCL reference.
The C# SDK uses standard XML Documentation Comments.
Docfx consumes these comments and generates a static documentation site.
To build the documentation, install docfx and run docfx docs/docfx.json --serve
.
Getting Help
If you are experiencing difficulties, contact our support team at support@freeclimb.com.


 Soon enough, the detective partners with a rookie cop and stumbles across a drug traffic ring. The next thing you know, they're both neck up in police corruption, car chases, explosions, rat-tat-tats and Steven Seagal's bigass chin!
CRITIQUE: Not bad, not bad at all. Surprisingly competent despite its many contrivances, this film is officially my first guilty pleasure of the year! And what does that mean? That means that as long as you don't take this film too seriously, and basically take it for what it is, which is a typical action flick with comic relief spread throughout, you will more than likely be quite entertained by it all. And to top it all off, this movie is not a Steven Seagal movie at all! In fact, even though his tubby face is on the poster and his name above the credits, this film has a multitude of characters, all of which add a little spice to the film's very basic ingredients. Yeah, sure the movie has its over-the-top moments, like the typical unappreciative head of the police demoting Seagal because he's a cop who doesn't play by the rules (even though he saved the vice-president's life!).  But for me, a few of these goofy scenarios didn't spoil the overall fun that I had watching this movie. And trust me...I was as surprised as anyone!! I don't particularly like Steven Seagal, the man or the actor, and never thought twice about any of his movies, but this flick thankfully doesn't focus on him, and that's a definite plus.
DMX is the real show-stopper here, giving us plenty of on-screen charisma, some kick-ass moves and even a healthy dose of acting shop 101. You go, boy!! The rest of the cast also helped take the emphasis off ol' chubface, and added some much needed humor into the mix as well, as both Tom Arnold and Anthony Anderson took the reigns and rode 'em whole in here. And speaking of those two, do not leave your seat at the end of the movie if you liked what they did in the flick, because there is another really humorous session between the two of them during the closing credits, that just put the icing on this fluffy cake. So what's good about the movie? Well, it's got lotsa gunplay, some wicked shots from the director, an actual story with surprises, despite its basic plot line of "crooked cops" which we've seen a thousand times, adrenalized action sequences, car chases and explosions and even some T&A (for the kids...hehe). The negatives include Seagal's acting talent, the obvious dummies and stunt people used in some of the sequences (geeeez, are we really supposed to believe that Seagal could even ride a motorcycle, no less, do the things done in this movie?), the somewhat preposterous denouement once everything is out in the open, and oh, did I mention Seagal?
Anyway, I think the people who go into this movie expecting to see some solid action, a few laughs and an overall forgettable story, will likely be quite entertained by it all. If you're looking to nail Seagal on his "same ol', same ol" character and the basic generic tone of the movie, then you could do that, too. But for me, I decided to take it as it came and I honestly can't say that the film wasn't an enjoyable one, despite its many faults. So take off that mask of cynicism and enjoy this movie for what it is...a fun, good ol' guilty pleasure of guns, explosions and Steven Seagal doing things with his body that we all know he can't really do without his faithful stuntmen by his side! No substance here, folks...just good ol' fashioned "guy stuff"!
Where's JoBlo coming from? The Corruptor (7/10) - Mission Impossible 2 (7/10) - Payback (8/10) - The Replacement Killers (6/10) - Romeo Must Die (3/10) - Ronin (8/10) - Shaft (7/10) - Traffic (8/10)
Review Date: March 16, 2001 Director: Andrzej Bartkowiak Writers: Ed Horowitz and Richard D'Ovidio Producers: Joel Silver and Dan Cracchiolo Actors: Steven Seagal DMX Tom Arnold Genre: Action Year of Release: 2001 ----------------------------------- JoBlo's Movie Emporium http://www.joblo.com/ ----------------------------------- (c) 2001 Berge Garabedian
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


LLVM: llvm-link tool
NAME
llvm-link
SYNOPSIS
llvm-link [options] <filename> [filename ...]
DESCRIPTION
The llvm-link command takes several LLVM bytecode files and links them
together into a single LLVM bytecode file. It writes the output file to
standard output, unless the -o option is used to specify a filename.
The llvm-link command attempts to load the input files from the current
directory. If that fails, it looks for each file in each of the
directories specified by the -L options on the command line. The library search
paths are global; each one is searched for every input file if necessary. The
directories are searched in the order they were specified on the command line.
OPTIONS
- -L <directory>
Add the specified directory to the library search path. When looking
for libraries, llvm-link will look in pathname for libraries.
This option can be specified multiple times; llvm-link will
search inside these directories in the order in which they were
specified on the command line.
- -f
Overwrite output files. By default, llvm-link will not
overwrite an output file if it alreadys exists.
- -o <filename>
Output filename. If filename is -, then llvm-link will write
its output to standard output.
- -d
If specified, llvm-link prints a human-readable version of the
output bytecode file to standard error.
- -help
Print a summary of command line options.
- -v
Verbose mode. Print information about what llvm-link is doing.
This typically includes a message for each bytecode file linked in
and for each library found.
EXIT STATUS
If llvm-link succeeds, it will exit with 0. Otherwise, if an error
occurs, it will exit with a non-zero value.
SEE ALSO
gccld
Maintained by the LLVM Team.


Donation
Thanks for donating!
You can use this CoinBase button to donate any amount. This is the easiest option.
Donate Bitcoins
Alternatively, you can donate however much you like to this bitcoin address:
19J43UNjckM9Q2M59ZM8ptCW5kA1dWdHdp
Again, thanks for donating! I'll be sure to put your name somewhere if your kindness overwhelms me. :)


{% extends "base.html" %} {% block content %} {% block content_title %}
I am a passionate self-taught software engineer (and lately site reliability engineer), a father to two lovely kids, a husband to an amazing wife, supposedly a geek, a caffeine junkie, a food lover, an open source/free software believer, and in a love/hate relationship with running. Originally from Cairo, Egypt. Currently living in the United Kingdom.
You can check my resume, jump to the bottom of the page to sees some recent blog posts, or go to my blog, see what I managed to do in the 2018 & 2019, and what I plan on doing in 2020, or hang around and check the rest of the links on this website.
Over the years, I have compiled and distilled a list of lists of useful resources. If you have any feedback please don't hesitate to send it my way.
Photo by: Amira Qassim
[{{ article.locale_date }}]
{{ article.title }}.


All the GEOS drawing commands are based on 16-bit coordinates. Drawing may only occur within a 16-bit graphics space. The graphics system does, however, support extended translations of the 16-bit graphics space within 32-bit coordinates.
This means that you can think of the large document space as a number of smaller, 16-bit "local" graphics spaces. When you need to draw anything, you first use an extended translation to get near your drawing point in the large document. Then you can draw using 16-bit offsets from the point to which you translated.
The application using the extended translation can do so in two different ways: It can store a 32-bit translation with each visible object, or it can store a 32-bit translation in a visible composite, thereby making the entire visible branch under the composite in a 32-bit graphics space. Visible trees implementing layer objects must use the second option; the layer must contain the translation for the entire visible branch that it manages. If a simple large visible tree does not need layers, it may wish to use the first solution.
The first of the two solutions is simple but takes up additional memory and time; each object, when it draws, must translate the coordinates, draw, then translate back. Two translations for each object could significantly affect drawing performance unless visual updates are handled carefully.
The other solution, storing a translation in the composite object, requires just two translations for the entire branch headed by the composite. Whenever the composite receives
MSG_VIS_DRAW
or
MSG_VIS_VUP_CREATE_GSTATE
, it executes the translation on the GState. As long as the translation is always relative to the GState's current transformation (done using
GrApplyTranslationDWord()
), and as long as the translation is undone before the GState is returned to the caller, drawing will be done properly.