class GRE_GROUP g_group =MainLayout.GetGroupByName("Group 1"); class GRDEVICE_MEM_RGB24 imgdev; class GRDEVICE_MEM_BINARY maskdev; class GC imagegc, maskgc; class GRE_GROUP group; proc OnLayoutLoadEnd ( class GRE_LAYOUT layout ) { group = layout.GetGroupByName("ProvinceMaps"); g_group = group; } func OnViewDataTipShowRequest ( class GRE_VIEW view, class POINT2D point, # Point in screen coordinates class TOOLTIP datatip ) { datatip.Delay = 500; datatip.String = ""; local class GRE_LAYER layer = g_group.FirstLayer; local class LABELPLACE place, places[]; local class GRE_LABELS labels; local class POINT2D offset, delta, oldcenter, newpt, groupcenter, groupdelta, center; local class REGION2D reg, groupreg; local class RECT extents, groupextents, oldextents; local numeric zoom = 2.0, q, angle, SolutionFound, dTheta; local class POINT2D offsets[]; local class LABELATTACHMENT attachment; local class POLYLINE leader; local class COLOR foregroundcolor; foregroundcolor.name = "red2"; offset.x = 10; # Offset so label doesn't fall under cursor offset.y = 10; imagegc = imgdev.CreateGC(); while (layer) { labels = layer.GetLabels(view); labels.GetItemAtLocation(point, place, 10); reg = place.GetRegion(); places = labels.GetItemsOverlappingRegion(reg); numeric number = places.GetNumItems(); if (number > 1) { # Find the extents of the labels as they are on the screen groupreg.Clear(); for q = 1 to number { groupreg.UnionRegion(places[q].GetRegion()); } groupextents = groupreg.Extents; groupcenter = groupextents.center; # Expand the extents so that our labels will be placed far enough # out for their leader lines to look good groupextents.Expand(10, 10); # Compute zoomed extents so we know how big to make our window # and decide where we'll place the labels while we're at it reg.Clear(); for q = 1 to number { place = places[q]; center = place.GetRegion().Extents.center; angle = groupcenter.GetAngle(center); # Remove the leaders so we don't try to zoom them place.SetCopyOnWrite(1); while (place.GetNumAttachments()) { place.DeleteAttachment(place.GetAttachment(1).Element); } zoom = 30 / place.GetRegion().Extents.GetHeight(); if (zoom < 1.0) zoom = 1.0; place.Zoom(zoom); dTheta = 0; SolutionFound = false; while (!SolutionFound && dTheta < 360) { # Move out from center until label no longer intersects # the extents of the actual labels delta.x = cos(angle); delta.y = sin(angle); extents = place.GetRegion().Extents; offset.x = groupcenter.x - extents.center.x; offset.y = groupcenter.y - extents.center.y; extents += offset; while (groupextents.Overlaps(extents)) { offset += delta; extents += delta; } # Make sure this label won't overlap another one. If it will, # move 10 degrees around and try again. If we get all the # way around the circle and still can't find a spot, give up. SolutionFound = reg.TestRect(extents, "FullOutside"); if (!SolutionFound) { dTheta += 10; angle += 10 / deg; } } offsets[q] = offset; place.Move(offset); reg.UnionRegion(place.GetRegion()); } groupdelta.x = -reg.Extents.x1; groupdelta.y = -reg.Extents.y1; imgdev.Create(reg.Extents.GetHeight()+5,reg.Extents.GetWidth()+5); imgdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters); imgdev.Clear("white"); imagegc = imgdev.CreateGC(); imagegc.SetOutputScale(view.GetMapScale()); maskdev.Create(imgdev.GetHeight(),imgdev.GetWidth()); maskdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters); maskdev.ClearAll(); maskgc = maskdev.CreateGC(); maskgc.SetOutputScale(view.GetMapScale()); maskgc.SetPixelFunction("Set"); for q = 1 to number { place = places[q]; oldextents = place.GetRegion().Extents; center = oldextents.center; oldextents += groupdelta; center += groupdelta; place.SetCopyOnWrite(1); # Remove the leaders so we don't try to zoom them while (place.GetNumAttachments()) { place.DeleteAttachment(place.GetAttachment(1).Element); } zoom = 30 / place.GetRegion().Extents.GetHeight(); if (zoom < 1.0) zoom = 1.0; place.Zoom(zoom); extents = place.GetRegion().Extents; delta = offsets[q] + groupdelta; extents += delta; newpt = extents.center; place.Move(delta); leader.Clear(); leader.AppendVertex(center); leader.AppendVertex(newpt); attachment.Leader = leader; place.AddAttachment(attachment); # Draw the label to use as an image tip place.DrawSample(imagegc, foregroundcolor); # Draw again into a mask device place.DrawSample(maskgc, foregroundcolor); } # Figure out where to place the tip newpt.x = -groupdelta.x; newpt.y = -groupdelta.y; offset = newpt - point; # Show the tip datatip.SetImageTip(imgdev, maskdev, offset); return (1); } else { # Single data tip case place = places[1]; extents = place.GetRegion().Extents; oldcenter = extents.center; # Make sure we're modifying a COPY of the place, not the original place.SetCopyOnWrite(1); # Remove the leaders so we don't try to zoom them while (place.GetNumAttachments()) { place.DeleteAttachment(place.GetAttachment(1).Element); } zoom = 30 / place.GetRegion().Extents.GetHeight();# THIS IS CATCHING THE LABEL SIZE, IF IT IS SMALLER THAN 1, DON'T DO BELOW... # Zoom it up. Maybe compute a zoom factor based on current size? if (zoom > 1.2) { place.Zoom(zoom); # Get new extents extents = place.GetRegion().Extents; # Move the label to (0,0) delta.x = -extents.x1; delta.y = -extents.y1; place.Move(delta); # Draw the label to use as an image tip imgdev.Create(extents.GetHeight()+2, extents.GetWidth()+2); imgdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters); imgdev.Clear("white"); imagegc = imgdev.CreateGC(); imagegc.SetOutputScale(view.GetMapScale()); place.DrawSample(imagegc,foregroundcolor); # Draw again into a mask device maskdev.Create(imgdev.GetHeight(),imgdev.GetWidth()); maskdev.SetPixelSizeMM(view.PixelSizeMillimeters, view.PixelSizeMillimeters); maskdev.ClearAll(); maskgc = maskdev.CreateGC(); maskgc.SetOutputScale(view.GetMapScale()); maskgc.SetPixelFunction("Set"); place.DrawSample(maskgc, foregroundcolor); # Figure out where to place the tip newpt.x = oldcenter.x - imgdev.GetWidth() / 2; newpt.y = oldcenter.y - imgdev.GetHeight() / 2; offset = newpt - point; # Show the tip datatip.SetImageTip(imgdev, maskdev, offset); return (1); } } layer = layer.NextLayer; } return (0); } proc OnViewDataTipHidden ( class GRE_VIEW view ) { # Insert code here }