# ELEMSEL.SML - Allows user to select and highlight the closest vector # point, line, or label or the enclosing polygon. # Created by: Mark Smith and Randy Smith # Most recent revision: 2-2002 # The following symbols are predefined # class VIEW View {use to access the view the tool script is attached to} # class GROUP Group {use to access the group being viewed if the script is run from a group view} # class LAYOUT Layout {use to access the layout being viewed if the script is run from a layout view} # # The following values are also predefined and are valid when the various On...() # functions are called which deal with pointer and keyboard events. # number PointerX Pointer X coordinate within view in pixels # number PointerY Pointer Y coordinate within view in pixels # Variable declarations class GRE_LAYER_VECTOR vectorLayer; class Vector targetVector; class GRE_GROUP activegroup; class XmForm elemwin, buttonRow; class XmLabel layerlabel, selectlabel; class GC gc; class XmDrawingArea da; class XmRowColumn selectMode; class XmTogglebutton pointButton, lineButton, polyButton; class XmSeparator line1; class PushButtonItem closeButton; string layerlabel$, mode$; numeric toolOpen; # Callback for drawing area expose; redraws window text. proc OnRedraw() { if (gc == 0) return; ActivateGC(gc); SetColorName("gray75"); FillRect(0, 0, da.width, da.height); SetColorName("black"); DrawInterfaceText("Active Layer: " + layerlabel$, 0, 10); } # Checks layer to see if it is valid. func checkLayer() { local numeric valid = true; # Get names layers if usable. If not output error messages. # Get name of active layer if it is usable. If not output an error message. if (activegroup.ActiveLayer.Type == "") { PopupMessage("Group has no layers!"); valid = false; selectlabel.Sensitive = 0; pointButton.Sensitive = 0; lineButton.Sensitive = 0; polyButton.Sensitive = 0; layerlabel$ = ""; } else if (activegroup.ActiveLayer.Type == "Vector") { vectorLayer = activegroup.ActiveLayer; layerlabel$ = activegroup.ActiveLayer.Name; selectlabel.Sensitive = 1; pointButton.Sensitive = 1; lineButton.Sensitive = 1; polyButton.Sensitive = 1; DispGetVectorFromLayer(targetVector, vectorLayer); } else { PopupMessage("Active layer not a vector!"); layerlabel$ = activegroup.ActiveLayer.Name; selectlabel.Sensitive = 0; pointButton.Sensitive = 0; lineButton.Sensitive = 0; polyButton.Sensitive = 0; valid = false; } OnRedraw(); return valid; } # Callback for when active layer changes. proc OnLayerChange() { if (toolOpen) checkLayer(); } # Callback for when user selects different vector selection mode. proc OnModeChanged() { if (pointButton.Set == 1) { if (targetVector.$Info.NumPoints < 1) { PopupMessage("No points!"); } else mode$ = "point"; activegroup.ActiveLayer.UnhighlightAllElements(); } else if (lineButton.Set == 1) { if (targetVector.$Info.NumLines < 1) { PopupMessage("No lines!"); } else mode$ = "line"; activegroup.ActiveLayer.UnhighlightAllElements(); } else if (targetVector.$Info.NumPolys < 1) { PopupMessage("No polygons!"); } else mode$ = "poly"; activegroup.ActiveLayer.UnhighlightAllElements(); } # Called when user presses 'left' pointer/mouse button. func OnLeftButtonPress () { # If the selected layer is not valid, don't do anything. if (checkLayer()) { # Set local variables local class POINT2D point; # Find cursor position in screen coordinates and transform to # map coordinates for active layer. point.x = PointerX; point.y = PointerY; point = TransPoint2D(point, ViewGetTransViewToScreen(View, 1)); point = TransPoint2D(point, ViewGetTransMapToView(View, vectorLayer.Projection, 1)); if (mode$ == "point") { local numeric elementNum = FindClosestPoint(targetVector, point.x, point.y, GetLastUsedGeorefObject(targetVector)); if (elementNum > 0) then vectorLayer.Point.HighlightSingle(elementNum); } else if (mode$ == "line") { elementNum = FindClosestLine(targetVector, point.x, point.y, GetLastUsedGeorefObject(targetVector)); if (elementNum > 0 ) then vectorLayer.Line.HighlightSingle(elementNum); } else if (mode$ == "poly") { elementNum = FindClosestPoly(targetVector, point.x, point.y, GetLastUsedGeorefObject(targetVector)); if (elementNum > 0 ) then vectorLayer.Poly.HighlightSingle(elementNum); } } } # end of OnLeftButtonPress # Callback for when the active group changes. proc cbGroup() { activegroup = Layout.ActiveGroup; } # Procedure for closing the tool dialog window. proc OnClose() { DialogClose(elemwin); toolOpen = false; } # Called the first time the tool is activated. # If the tool implements a dialog it should be created (but not displayed) here. func OnInitialize () { if (Layout) { WidgetAddCallback(Layout.GroupSelectedCallback, cbGroup); activegroup = Layout.ActiveGroup; } else { activegroup = Group; WidgetAddCallback(Group.LayerSelectedCallback, OnLayerChange); } # Set up tool dialog window. elemwin = CreateFormDialog("Select Element"); elemwin.marginHeight = 5; elemwin.marginWidth = 5; WidgetAddCallback(elemwin.Shell.PopdownCallback, OnClose); # Add drawing area for layer identifier text. da = CreateDrawingArea(elemwin, 12, 180); da.TopWidget = elemwin; da.LeftWidget = elemwin; da.LeftOffset = 5; da.RightWidget = elemwin; da.RightOffset = 5; WidgetAddCallback(da.ExposeCallback, OnRedraw); # Add select label text. selectlabel = CreateLabel(elemwin, "Select: "); selectlabel.TopWidget = da; selectlabel.TopOffset = 4; selectlabel.LeftWidget = elemwin; selectlabel.RightWidget = selectlabel; # unattached # Add form for element type toggle buttons. selectMode = CreateRowColumn(elemwin, 1); selectMode.Orientation = "VERTICAL"; selectMode.TopWidget = selectlabel; selectMode.LeftWidget = elemwin; selectMode.LeftOffset = 20; selectMode.RightWidget = elemwin; selectMode.RadioBehavior = 1; # Add radio button for points. pointButton = CreateToggleButton(selectMode, "Closest Point"); WidgetAddCallback(pointButton.ValueChangedCallback, OnModeChanged); # Add radio button for lines. lineButton = CreateToggleButton(selectMode, "Closest Line"); WidgetAddCallback(lineButton.ValueChangedCallback, OnModeChanged); # Add radio button for polygons. polyButton = CreateToggleButton(selectMode, "Enclosing Polygon"); WidgetAddCallback(polyButton.ValueChangedCallback, OnModeChanged); # Add separator between selection buttons and close button. line1 = CreateHorizontalSeparator(elemwin); line1.TopWidget = selectMode; line1.TopOffset = 5; line1.LeftWidget = elemwin; line1.RightWidget = elemwin; # Add button to close window. closeButton = CreatePushButtonItem("Close", OnClose); # Create form for pushbutton row. buttonRow = CreateButtonRow(elemwin, closeButton); buttonRow.TopWidget = line1; buttonRow.LeftWidget = elemwin; buttonRow.RightWidget = elemwin; } # end of OnInitialize # Called when tool is activated. func OnActivate () { toolOpen = true; checkLayer(); # Reset dialog window defaults pointButton.Set = 1; lineButton.Set = 0; polyButton.Set = 0; mode$ = "point"; if (activegroup.ActiveLayer.Type == "Vector") then activegroup.ActiveLayer.UnhighlightAllElements(); DialogOpen(elemwin); if (gc == 0) then gc = CreateGCForDrawingArea(da); OnRedraw(); } # end of OnActivate # Called when tool is deactivated (usually when switching to another tool). func OnDeactivate () { OnClose(); } # end of OnDeactivate # Called when tool is to be destroyed, will not be called if tool was never activated. func OnDestroy () { DestroyGC(gc); DestroyWidget(elemwin); } # end of OnDestroy