When instances of a certain subclass of GoObjects get selected, either by (ctrl+)clicking or drawing a selection rect, I would like to add additional items to the selection.
An Object.OnGetSelection override does not appear to let me do this; the documentation states that it should not change which objects are selected.
Should I use a GoView.OnObjectSelected override ?
Or should I subclass GoToolSelecting ?
Both Object.OnGotSelection and GoView.OnObjectSelected are documented as “should not modify the selection”.
ok… I decided to take the path of implementing a new GoToolSelecting.
public class GoToolSelecting2 : GoToolSelecting {
// GoView.PickObject and GoDocument.PickObject will enforce selectability
this.CurrentObject = this.View.PickObject(true, false, evt.DocPoint, true); // only selectable document objects
//this.CurrentObjectWasSelected = this.View.Selection.Contains(this.CurrentObject);
if (evt.Control) {
this.Selection.Toggle(this.CurrentObject);
}
else if (evt.Shift) {
this.Selection.Add(this.CurrentObject);
}
else {
//this.Selection.Select(this.CurrentObject); ... this is what DoSelect did before.
GoBasicNode bn = this.CurrentObject as GoBasicNode;
if (bn != null) {
coll.Add(bn); // first
string first = bn.Text.Substring(0, 1); // select all nodes that start with same first char
if (o != bn && o is GoBasicNode) {
GoBasicNode n = o as GoBasicNode;
if (n.Text.StartsWith(first)) coll.Add(n);
}
}
}
if (coll.Count > 1) {
this.Selection.Clear();
this.Selection.AddRange(coll); // will do RaiseSelectionStarting, add, add, add..., RaiseSelectionFinished
}
else
this.Selection.Select(this.CurrentObject); // nope, just the one
}
}
else if (!evt.Control && !evt.Shift) {
this.Selection.Clear();
}
}
[/code]
Thanks, that provides a start…
-Basically, objects with this custom selection behavior will calculate a collection of additional items that need to get selected (or deselected).
-It needs to work for all user initiated selection/deselection operations.
-Subclasses are not important (for now at least).
To handle drag-box selection I guess this means I need to subclass GoToolRubberBanding ?
I should say a bit more about why I chose to do this with a Tool as opposed to creating a new GoSelection class and overriding Add.
Here’s a quick equivalent for the GoToolRubberBanding
// Setup by:
// goView1.ReplaceMouseTool(typeof(GoToolRubberBanding), new RubberBandTool2(goView1));
[Serializable]
public class RubberBandTool2 : GoToolRubberBanding {
public RubberBandTool2(GoView view)
: base(view) {
this.AutoScrolling = true;
}
/// <summary>
/// This method is called as part of the mouse up event, normally to select
/// the objects within the <paramref name="box"/>.
/// </summary>
/// <param name="box">a <c>Rectangle</c> describing what the user outlined, in view coordinates</param>
/// <remarks>
/// By default this will call <see cref="GoView.SelectInRectangle"/>, after converting
/// the <paramref name="box"/> into document coordinates.
/// If the box is too small in width and height, this acts like a normal mouse click instead.
/// </remarks>
public override void DoRubberBand(Rectangle box) {
if (!IsBeyondDragSize()) {
DoSelect(this.LastInput);
// whether or not we found and/or selected anything, call DoClick
DoClick(this.LastInput);
}
else {
RectangleF docRect = this.View.ConvertViewToDoc(box);
SelectInRectangle(docRect); // not this.View.
}
}
// copied and modified from GoView...
public virtual void SelectInRectangle(RectangleF rect) {
// keep everything in a separate collection, in case adding to the
// selection changes the selection...
ArrayList coll = new ArrayList();
foreach (GoLayer layer in this.View.Layers) {
if (!layer.IsInDocument) continue;
if (!layer.CanViewObjects()) continue;
if (!layer.CanSelectObjects()) continue;
foreach (GoObject obj in layer) {
selectObjectInRectangle(obj, rect, coll);
}
}
foreach (GoObject obj in coll) {
this.Selection.Add(obj);
}
}
private void selectObjectInRectangle(GoObject obj, RectangleF rect, ArrayList coll) {
if (!obj.CanView())
return;
if (obj.CanSelect() &&
((obj.SelectionObject != null) ?
obj.SelectionObject.ContainedByRectangle(rect) :
obj.ContainedByRectangle(rect))) {
coll.Add(obj);
AddObjectsRelatedTo(obj, coll);
}
else if (obj is GoGroup) {
this.Selection.Remove(obj);
GoGroup g = (GoGroup)obj;
foreach (GoObject o in g.GetEnumerator()) {
selectObjectInRectangle(o, rect, coll);
}
}
else {
this.Selection.Remove(obj);
}
}
private void AddObjectsRelatedTo(GoObject obj, ArrayList coll) {
GoBasicNode bn = obj as GoBasicNode;
// if the just picked item is a GoBasicNode, select all the nodes in doc that .Text starts with same char
if (bn != null) {
//coll.Add(bn);
string first = bn.Text.Substring(0, 1); // select all nodes that start with same first char
foreach (GoObject o in this.View.Document) {
if (o != bn && o is GoBasicNode) {
GoBasicNode n = o as GoBasicNode;
if (n.Text.StartsWith(first) && (coll.IndexOf(n) == -1) ) coll.Add(n);
}
}
}
}
}
Thanks, I got it working.
I decided I only needed the GoToolSelecting subclass.