Hi,
We’re using goXam in our application (WPF, 1.0.1.3), and I’m trying to get the Overview component to have the same behavior as the GoOverview control, namely the selectable/draggable zoom (creating the Bounding Box by holding and dragging the left mouse button).
Not sure how to do this. I guess I have to either implement a custom DragSelectingTool or DragZoomingTool (or both), but I was wondering if there was an easier way to do this.
Thanks,
B.
I think this shouldn’t be too hard to implement. I’ll take a look when I get a chance.
I haven’t tried this in 1.0.*, but I have tried this in 1.1.7.
First, let’s customize the Overview.Box, mostly to specify a Cursor:
<go:Overview x:Name="myOverview" . . .>
<go:Overview.BoxTemplate>
<DataTemplate>
<Rectangle Stroke="Blue" StrokeThickness="12" Fill="Transparent"
go:Part.LayerName="Tool" Cursor="SizeAll" />
</DataTemplate>
</go:Overview.BoxTemplate>
</go:Overview>
We’ll replace the standard Overview tool that handles mouse down/move/up (it’s internal – not public). And we’ll make use of a DragZoomingTool.
Instead of having two separate tools, we’ll just define one that acts either like the one that scrolls the Overview.Observed diagram or that acts like a regular DragZoomingTool. The StartedOverBox property is set when the tool activates; the property controls whether the tool acts like a DragZoomingTool or not.
[code] public class CustomDragZoomingTool : DragZoomingTool {
public override bool CanStart() {
if (!this.MouseEnabled) return false;
if (this.Diagram == null || !(this.Diagram is Overview)) return false;
if (!IsLeftButtonDown()) return false;
return true;
}
public override void DoActivate() {
base.DoActivate();
Overview ov = this.Diagram as Overview;
if (ov == null) return;
Node node = ov.Panel.FindElementAt<Node>(ov.LastMousePointInModel, x => Part.FindAncestor<Node>(x as Visual),
x => true, SearchLayers.Temporary | SearchLayers.Nodes);
this.StartedOverBox = (node != null && node.Layer.IsTemporary);
if (this.StartedOverBox) {
Point last = ov.LastMousePointInModel;
Point boxpos = node.Position;
this.Offset = new Point(last.X-boxpos.X, last.Y-boxpos.Y);
}
}
private bool StartedOverBox { get; set; }
private Point Offset { get; set; }
public override void DoMouseMove() {
if (!this.Active) return;
if (this.StartedOverBox) {
ScrollObserved();
} else {
base.DoMouseMove();
}
}
public override void DoMouseUp() {
if (!this.Active) return;
if (this.StartedOverBox || !IsBeyondDragSize()) {
ScrollObserved();
StopTool();
} else {
base.DoMouseUp();
}
}
private void ScrollObserved() {
Overview ov = this.Diagram as Overview;
if (ov != null && ov.Observed != null) {
Diagram obdiag = ov.Observed;
DiagramPanel obpanel = obdiag.Panel;
if (obpanel != null) {
Rect viewport = obpanel.ViewportBounds;
Point pt = ov.LastMousePointInModel;
obpanel.Position = new Point(pt.X-this.Offset.X, pt.Y-this.Offset.Y);
}
}
}
public override void ZoomToRect(Rect brect) {
Diagram observed = this.ZoomedDiagram;
if (observed == null) observed = this.Diagram;
if (observed == null || this.Diagram == null) return;
double vrectw = observed.Panel.ViewportWidth;
// do scale first, so DiagramPanel.NormalizePosition isn't constrained unduly when increasing scale
observed.Panel.Scale = Math.Min(vrectw/brect.Width, 4);
observed.Panel.Position = new Point(brect.X, brect.Y);
}
}[/code]
Finally, here’s how we’ll set it up: by removing the standard Overview tool and installing our custom one. Just for simplicity we’ll remove all of the standard mouse tools.
[code] // setup the Overview control later, when both controls have been initialized
this.Loaded += (s, e) => {
myOverview.MouseDownTools.Clear();
myOverview.MouseMoveTools.Clear();
myOverview.MouseUpTools.Clear();
myOverview.DragZoomingTool = new CustomDragZoomingTool();
myOverview.DragZoomingTool.ZoomedDiagram = myDiagram;
myOverview.Observed = myDiagram;
};[/code]
Thank you very much, Walter.
I’m trying this right now.
B.