Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
## PropFinder.sml
## 6 May 2004
## Revised 31 January 2007
## Requires the 2nd Edition of the Lincoln Property Atlas (with updated
## property database structure) and TNTmips v 7.2, 15 Mar 2006 or later
## DoZoom procedure: added flag that is checked for manual zooming of view.
## Revised 2 June 2010
## Parent of script dialog set to drawing area of view for
## compatability with Display changes made for 2008:74 and later versions.
## Fixed height of text fields on Address Search tabbed panel.
## Randy Smith, MicroImages, Inc.
## Tool script that creates a dialog to conduct property searches
## by address and by property owner for the Lincoln property database.
## The tool also provides three alternative left-mouse button actions:
## 1) zoom in to the mouse location, 2) zoom out from the mouse location
## and 3) select property parcel and show that property's page on the
## county assessor's website.
## Results of address or name searches are shown on the Result List
## tabbed panel. If only one match is found the property polygon is
## automatically highlighted and the view window recenters on that
## property polygon. If more than one match is found, the user
## should select an entry from the list and press the View Property button
## to highlight and recenter on the associated parcel polygon. In either
## case, if the highlighted polygon is already in the view, the view is not
## redrawn. The View Assessor's Website Data button on the same panel shows
## the selected property's page on the county assessor's website.
# The following symbols are predefined
# class GRE_VIEW View {use to access the view the tool script is attached to}
# class GRE_GROUP Group {use to access the group being viewed if the script is run from a group view}
# class GRE_LAYOUT Layout {use to access the layout being viewed if the script is run from a layout view}
# numeric ToolIsActive Will be 0 if tool is inactive or 1 if tool is active
#
# The following values are also predefined and are valid when the various On...()
# functions are called which deal with pointer and keyboard events.
# numeric PointerX Pointer X coordinate within view in pixels
# numeric PointerY Pointer Y coordinate within view in pixels
# numeric ShiftPressed 1 if <shift> key being pressed or 0 if not
# numeric CtrlPressed 1 if <ctrl> key being pressed or 0 if not
# numeric LeftButtonPressed 1 if left pointer button pressed or 0 if not
# numeric RightButtonPressed 1 if right pointer button pressed or 0 if not
# numeric MiddleButtonPressed 1 if middle pointer button pressed or 0 if not
########################################
### Global variable declarations
########################################
class GRE_LAYER_VECTOR parcelLayer;
class GRE_LAYER_RASTER orthoLayer;
class VECTOR parcelVector;
class RASTER orthoRaster;
class GRE_VECTOR_POLYS parcelPolys;
class TRANSPARM pTransparm; ## coordinate transformation parameters from screen to parcel layer
class TRANSPARM lvTransparm; ## coordinate transformation parameters from parcel layer to view
class RECT polyExtents, viewExtents; ## extents of polygon and view in screen coordinates
numeric searchmode; # 1 if address search, 0 if name search
numeric prevsearchmode; # mode for last search
numeric zoomChanged; # 1 if zoom has changed since last redraw, otherwise 0
numeric i; # element number counter for polygon loop
numeric count; # counter for number of property polygons found
numeric numPolys; # number of polygons in parcel vector
numeric matchRecList[1]; # array to hold record numbers for records matching search
numeric propsArray[1]; # array to hold element numbers of polygons found
numeric listcount; # number of items in result list in dialog
string xmlfile$;
class XMLDOC dlgdoc, listdlgdoc; # class instances for XML documents with dialog specifications
class XMLNODE dlgnode, listdlgnode; # class instance for node in the XML document corresponding
# to the dialog
class GUI_DLG dlgwin; # class instance for the GUI dialog
numeric errXML; # error value to check ingest of dialog specification
numeric prevMulti; # flag for previous search result type: 1 = multiple, 0 = other
numeric prevScale; # map scale the last time the doZoom procedure redrew the view
string prevname$; # string variable to store owner name for comparison before next search
string prevaddress$; # string variable to store address for comparison before next search
class GUI_FORMDATA settings; # structure to hold values retrieved from main search dialog
## handles for dialog controls, needed to clear/reset values on close
class GUI_LAYOUT_BOOK panels;
class GUI_CTRL_EDIT_NUMBER editAddNum;
class GUI_CTRL_EDIT_STRING editStreet, editLname, editFname, editMid;
class GUI_CTRL_COMBOBOX prefixCombo, streetTypeCombo;
class GUI_CTRL_EDIT_STRING statusText, searchText;
class GUI_FORM_RADIOGROUP zoomSetting, mouseSetting;
class GUI_CTRL_LISTBOX propList;
class GUI_CTRL_PUSHBUTTON viewProperty, viewData;
##################################################################################
# The following script functions will be called (if used in the script) when
# the appropriate action or event occurs as described in the comments before each.
# To use a function, uncomment the lines containing the 'func' definition
# and ending brace '}' by removing the leftmost '#' on the line and add the
# function code between the two lines.
##################################################################################
##################################################################################
#### procedure called the first time the tool is activated.
#### If the tool implements a dialog it should be created (but not displayed) here.
##################################################################################
proc OnInitialize ()
{
searchmode = 1; # set default search mode to address search
prevMulti = 0; # reinitialize flag for previous search result type
#######################################################################################
### get screen pixel size and compute map scale for 1X view of orthophoto layer
### (ortho cell size = 0.3 m = 3000 mm); scale at 1X = cell size (mm) / pixel size (mm)
#######################################################################################
numeric pixelSize = View.PixelSizeMillimeters; # screen pixel size in millimeters
numeric scale1X = 300 / pixelSize;
### get handles for the parcel vector layer in the View and its polygon element set
####################################################################################
Group = Layout.FirstGroup;
while (Group.Name != "Overlays")
Group = Group.NextGroup;
parcelLayer = Group.GetLayerByName("Parcels");
parcelLayer.NoFillWhenHighlight = 1; # don't fill highlighted polygons with highlight color
parcelPolys = parcelLayer.Poly;
### get the parcel vector object in parcelLayer so its database can be accessed
###############################################################################
DispGetVectorFromLayer(parcelVector, parcelLayer);
numPolys = NumVectorPolys(parcelVector);
### get TRANSPARM from parcel layer object coordinates to View coordinates
### to be used with left mouse button zoom function
###########################################################################
lvTransparm = View.GetTransLayerToView(parcelLayer);
###############################################
#### specification in XML for main query dialog
###############################################
local string xml$ = '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "smlforms.dtd">
<root>
<dialog id="pSearch" Title="Property Finder" Buttons="">
<book id="panels">
<page Name="Settings">
<pane Orientation="horizontal">
<groupbox Name=" Left mouse-button action: " ExtraBorder="3">
<radiogroup id="mouseSetting" Orientation="vertical" VertAlign="Top" HorizAlign="center" VertResize="Fixed" Default="zoom">
<item Value="zoomIn">Zoom In to Location</item>
<item Value="zoomOut">Zoom Out from Location</item>
<item Value="navigate">View Assessor's Website Data</item>
</radiogroup>
</groupbox>
<groupbox Name=" Zoom When Search: " ExtraBorder="3">
<radiogroup id="zoomSetting" Orientation="vertical" VertResize="Fixed" HorizAlign="center" Default="property" OnSelection="OnZoomChanged()">
<item Value="property">Zoom to Property</item>
<item Value="block">Zoom to Block</item>
<item Value="neighborhd">Zoom to Neighborhood</item>
<item Value="current">Keep Current Scale</item>
</radiogroup>
</groupbox>
</pane>
</page>
<page id="addressPage" Name="Address Search" OnSetActive="OnAddressActive()">
<pane Orientation="horizontal">
<pane Orientation="vertical">
<label>Number</label>
<editnumber id="addnumfld" BlankZero="true" Enabled="true" Format="Decimal"
HorizAlign="Left" Justify="right" Precision="0" VertResize="Fixed"/>
<label>1440</label>
<label>555</label>
</pane>
<pane Orientation="vertical" VertAlign="Top">
<label>Prefix</label>
<combobox id="comboPrefix" Enabled="true" Width="10" Default="ANY" HorizAlign="Left">
<item Value="ANY">Any</item>
<item Value="NONE">None</item>
<item Value="E">E</item>
<item Value="W">W</item>
<item Value="N">N</item>
<item Value="S">S</item>
<item Value="NW">NW</item>
<item Value="SW">SW</item>
</combobox>
<label>W</label>
<label>S</label>
</pane>
<pane Orientation="vertical" VertAlign="Top">
<label>Street Name</label>
<edittext id="streetnamefld" Enabled="true" HorizAlign="Right"
ReadOnly="false" Width="20" VertResize="Fixed"/>
<label>Pioneers</label>
<label>10</label>
</pane>
<pane Orientation="vertical" VertAlign="Top">
<label>Type</label>
<combobox id="comboType" Default="ANY" Enabled="true" Width="10" HorizAlign="Left"
Sort="false" Height="10">
<item Value="ANY">Any</item>
<item Value="AVE">AVE</item>
<item Value="BLVD">BLVD</item>
<item Value="CIR">CIR</item>
<item Value="CT">CT</item>
<item Value="DR">DR</item>
<item Value="LN">LN</item>
<item Value="RD">RD</item>
<item Value="ST">ST</item>
<item Value="BAY">BAY</item>
<item Value="BND">BND</item>
<item Value="BYP">BYP</item>
<item Value="HOLW">HOLW</item>
<item Value="HWY">HWY</item>
<item Value="MALL">MALL</item>
<item Value="PKWY">PKWY</item>
<item Value="PL">PL</item>
<item Value="PLZ">PLZ</item>
<item Value="PP">PP</item>
<item Value="TER">TER</item>
<item Value="TRL">TRL</item>
<item Value="VAL">VAL</item>
</combobox>
<label>BLVD</label>
<label>ST</label>
</pane>
</pane>
</page>
<page id="namePage" Name="Owner Name Search" OnSetActive="OnNameActive()">
<pane Orientation="horizontal">
<pane Orientation="vertical" VertResize="Fixed" VertAlign="Center">
<label VertAlign="Bottom">Last Name</label>
<edittext id="lastnamefld" Enabled="true" HorizAlign="Left"
ReadOnly="false" Width="20" VertResize="Fixed"/>
</pane>
<pane Orientation="vertical" VertResize="Fixed" VertAlign="Center">
<label VertAlign="Bottom">First Name</label>
<edittext id="firstnamefld" Enabled="true" HorizAlign="Left"
ReadOnly="false" Width="20" VertResize="Fixed"/>
</pane>
<pane Orientation="vertical" VertResize="Fixed" VertAlign="Center">
<label VertAlign="Bottom">Middle Initial</label>
<edittext id="midintfld" Enabled="true" HorizAlign="Left"
ReadOnly="false" Width="20" MaxLength="1" VertResize="Fixed"/>
</pane>
</pane>
</page>
<page Name="Result List">
<pane Orientation="horizontal">
<label HorizResize="Fixed">You searched for:</label>
<edittext id="searchText" ReadOnly="true" Width="40" HorizAlign="Left"/>
</pane>
<listbox id="propList" SelectStyle="single" Width="60" OnChangeSelection="OnPropListSelect()" OnDoubleClick="OnViewPoly()">
</listbox>
<pane Orientation="horizontal" HorizAlign="Right">
<label HorizResize="Expand"> </label>
<pushbutton id="viewProperty" Name=" View Highlighted Property " HorizResize="Fixed" Enabled="no" OnPressed="OnViewPoly()"/>
<pushbutton id="viewData" Name=" View Assessor's Website Data " HorizResize="Fixed" Enabled="no" OnPressed="OnViewData()"/>
</pane>
</page>
</book>
<pane Orientation="horizontal">
<label HorizResize="Fixed">Search Status:</label>
<edittext id="statusText" ReadOnly="true" Width="40" HorizAlign="Left"/>
</pane>
<pane Orientation="horizontal" HorizAlign="Right">
<label HorizResize="Expand"> </label>
<pushbutton id="searchbutton" Name=" Search " HorizResize="Fixed" WidthGroup="1" OnPressed="OnSearch()"/>
<pushbutton id="closebutton" Name="Close" HorizResize="Fixed" WidthGroup="1" OnPressed="OnClose()"/>
<pushbutton id="helpbutton" Name=" Help " HorizResize="Fixed" WidthGroup="1" OnPressed="OnHelp()"/>
</pane>
</dialog>
</root>';
################################################################
### parse XML text for main search dialog into memory;
### return an error code (number < 0) if there are syntax errors
################################################################
errXML = dlgdoc.Parse(xml$);
if (errXML < 0)
{
PopupError(errXML);
Exit();
}
##########################################################
# get the dialog element from the parsed XML document and
# show error message if the dialog element can't be found
##########################################################
dlgnode = dlgdoc.GetElementByID("pSearch");
if (dlgnode == 0)
{
PopupMessage("Could not find dialog node in XML document");
Exit();
}
##########################################################
# Set the XML dialog element as the source for the GUI_DLG
# class instance we are using for the dialog window.
##########################################################
dlgwin.SetXMLNode(dlgnode);
dlgwin.CreateModeless(View.DrawingArea); ### create as modeless dialog with
### View window drawing area as parent
################################################################################
### get handles for dialog controls using their ID's in the dialog specification
################################################################################
statusText = dlgwin.GetCtrlByID("statusText");
searchText = dlgwin.GetCtrlByID("searchText");
zoomSetting = dlgwin.GetCtrlByID("zoomSetting");
mouseSetting = dlgwin.GetCtrlByID("mouseSetting");
propList = dlgwin.GetCtrlByID("propList");
panels = dlgwin.GetPaneByID("panels");
viewProperty = dlgwin.GetCtrlByID("viewProperty");
viewData = dlgwin.GetCtrlByID("viewData");
### address controls
editAddNum = dlgwin.GetCtrlByID("addnumfld");
prefixCombo = dlgwin.GetCtrlByID("comboPrefix");
editStreet = dlgwin.GetCtrlByID("streetnamefld");
streetTypeCombo = dlgwin.GetCtrlByID("comboType");
### name controls
editLname = dlgwin.GetCtrlByID("lastnamefld");
editFname = dlgwin.GetCtrlByID("firstnamefld");
editMid = dlgwin.GetCtrlByID("midintfld");
} # end of OnInitialize
#############################################################################
### Called when tool is activated.
### If the tool implements a dialog it should be "managed" (displayed) here.
#############################################################################
proc OnActivate () {
# panels.SetActivePage(0); ### set Settings panel to be active (on top)
dlgwin.Open();
zoomChanged = 1;
} # end of OnActivate
############################################################################
### Called when tool is deactivated (usually when switching to another tool).
### If the tool implements a dialog it should be "unmanaged" (hidden) here.
############################################################################
proc OnDeactivate () {
### clear/reset controls on main search dialog to default states
statusText.ClearValue(0);
editAddNum.ClearValue(0);
prefixCombo.SetSelectedItemIndex(0);
editStreet.ClearValue(0);
streetTypeCombo.SetSelectedItemIndex(0);
editLname.ClearValue(0);
editFname.ClearValue(0);
editMid.ClearValue(0);
if (propList.GetCount() > 0) then ### clear property list
propList.DeleteAllItems();
dlgwin.Close(0); # close search dialog without notifying, so OnClose()
# will not be called (allows user to switch tools without
# having OnClose() override by setting the default tool
} # end of OnDeactivate
#############################################################################
### procedure called when Help button on dialog is pressed
#############################################################################
proc OnHelp ()
{
local string url$;
url$ = "file://" + _context.ScriptDir + "/" + "help.htm";
RunAssociatedApplication(url$);
}
##############################################################
### procedure called when the Address Search page is activated
##############################################################
proc OnAddressActive ()
{
searchmode = 1;
statusText.ClearValue(0);
editAddNum.SetFocus();
} # end of OnAddressActive
############################################################
### procedure called when the Name Search page is activated
############################################################
proc OnNameActive ()
{
searchmode = 0;
statusText.ClearValue(0);
editLname.SetFocus();
} # end of OnNameActive
###########################################################
### Called when user presses 'left' pointer/mouse button.
###########################################################
proc OnLeftButtonPress ()
{
local string mouseSetting$;
local class POINT2D clickPt; ### coordinates for click position
### get setting for left mouse button mode from dialog
mouseSetting$ = mouseSetting.GetValueStr();
### get cursor position in screen coordinates
clickPt.x = PointerX;
clickPt.y = PointerY;
### get TRANSPARM from screen coordinates to parcel vector layer coordinates
### for current view position and transform point to layer coordinates
############################################################################
pTransparm = View.GetTransLayerToScreen(parcelLayer, 1);
clickPt = pTransparm.ConvertPoint2DFwd(clickPt);
if (mouseSetting$ == "navigate") ### select polygon and go to its page on Assesor's website
{
local numeric polynum; ### element number of the polygon clicked on
local string url$; ### string containing the URL to pass to the browser
### find the polygon clicked on and highlight it in the view
polynum = FindClosestPoly(parcelVector, clickPt.x, clickPt.y, GetLastUsedGeorefObject(parcelVector) );
parcelPolys.HighlightSingle(polynum);
url$ = parcelVector.poly[polynum].ca062506.P_I_D$;
RunAssociatedApplication(url$);
}
else if (mouseSetting$ == "zoomIn") ### zoom in to cursor position
{
### convert click point from vector layer to view coordinates
### using TRANSPARM computed when tool is initialized
#############################################################
clickPt = lvTransparm.ConvertPoint2DFwd(clickPt);
View.DisableRedraw = 1;
View.Center = clickPt; ### recenter View on click point
View.ZoomIn(2,1); ### zoom in 2X
View.DisableRedraw = 0;
View.Redraw(); ### redraw view
}
else if (mouseSetting$ == "zoomOut") ### zoom out from cursor position
{
### convert click point from vector layer to view coordinates
### using TRANSPARM computed when tool is initialized
#############################################################
clickPt = lvTransparm.ConvertPoint2DFwd(clickPt);
View.DisableRedraw = 1;
View.Center = clickPt; ### recenter View on click point
View.ZoomOut(2,1); ### zoom out 2X
View.DisableRedraw = 0;
View.Redraw(); ### redraw view
}
} # end of OnLeftButtonPress
###########################################################
### procedure called when zoom setting is changed in dialog
###########################################################
proc OnZoomChanged ()
{
zoomChanged = 1;
} # end of OnZoomChanged
##########################################################################
### procedure to highlight, pan, and zoom to the selected property polygon
##########################################################################
proc DoZoom (numeric element)
{
local numeric vwScale;
local string zoom$;
#######################################################
### check if highlighted polygon is already in the view
#######################################################
### get extents of highlighted polygon from Internal database table as min and max points
local CLASS POINT2D minPt, maxPt;
minPt.x = parcelVector.poly[element].Internal.MinX;
minPt.y = parcelVector.poly[element].Internal.MinY;
maxPt.x = parcelVector.poly[element].Internal.MaxX;
maxPt.y = parcelVector.poly[element].Internal.MaxY;
### set up RECT from polygon extents
polyExtents.pt1 = minPt;
polyExtents.pt2 = maxPt;
### get extents of View in screen coordinates
### upper left corner of view pane = 0,0, so lower right coordinates = width, height
local CLASS POINT2D UpLeft, LowRight;
LowRight.x = View.Width;
LowRight.y = View.Height;
### set up RECT from view extents in screen coordinates
viewExtents.pt1 = UpLeft;
viewExtents.pt2 = LowRight;
vwScale = ViewGetMapScale(View); # get current view scale
if (zoomChanged == 0 && vwScale == prevScale) ### zoom setting hasn't been changed and view hasn't been manually zoomed;
{ ### don't need to check zoom setting
#################################################################################
### get TRANSPARM from screen coordinates to parcel vector layer coordinates for
### current view position and convert extents RECT to layer coordinates
#################################################################################
pTransparm = View.GetTransLayerToScreen(parcelLayer, 1);
viewExtents = pTransparm.ConvertRectFwd(viewExtents);
###############################################################################
### check if parcel polygon is in the current view
###############################################################
if (viewExtents.ContainsRect(polyExtents) ) ### don't need to redraw view
{
View.SetMessage(""); ### clear View window message line and status bar
View.StatusBarClear();
}
else
{
View.DisableRedraw = 1;
#################################################################################
### if parcel polygon won't fit in view at this scale, then zoom to polygon extents
### before redrawing.
#################################################################################
if ( (polyExtents.GetHeight() > viewExtents.GetHeight() ) ||
(polyExtents.GetWidth() > viewExtents.GetWidth() ) )
{
parcelLayer.ZoomToActiveElement();
parcelLayer.UnhighlightAllElements(); ### needed to force redraw
zoomChanged = 1;
}
else # parcel polygon fits in view; pan to polygon and set current map scale
{
vwScale = View.CurrentMapScale; # get current view scale
parcelLayer.ZoomToActiveElement(); # zooms to polygon extents, changing view scale
View.CurrentMapScale = vwScale; # reset previous view scale
parcelLayer.UnhighlightAllElements(); # needed to force redraw
}
###################################################################
### re-enable redraw, redraw the view, and highlight the polygon
###################################################################
View.DisableRedraw = 0;
ViewRedraw(View);
parcelPolys.HighlightSingle(element);
}
} # end (if zoomChanged == 0)
else ### zoom setting has changed
{
### get current setting for Zoom radiogroup
zoom$ = zoomSetting.GetValueStr();
View.DisableRedraw = 1;
if (zoom$ == "property") ## zoom to 1X but don't redraw yet
{
vwScale = scale1X;
}
else ### set vwScale value from Zoom radiogroup setting
{
if (zoom$ == "current") then
vwScale = ViewGetMapScale(View);
else if (zoom$ == "block") then
vwScale = 3200;
else if (zoom$ == "neighborhd") then
vwScale = 8000;
}
### Set View scale, zoom / recenter on active polygon but don't redraw yet
parcelLayer.ZoomToActiveElement();
ViewSetMapScale(View, vwScale);
parcelLayer.UnhighlightAllElements();
#####################################################################################
### get TRANSPARM from screen coordinates to parcel vector layer coordinates for the
### new view position and view scale and convert extents RECT to layer coordinates
#####################################################################################
pTransparm = View.GetTransLayerToScreen(parcelLayer, 1);
viewExtents = pTransparm.ConvertRectFwd(viewExtents);
##################################################################################
### if parcel polygon won't fit in view at new zoom, then zoom to polygon extents
### before redrawing.
###################################################################################
if ( (polyExtents.GetHeight() > viewExtents.GetHeight() ) ||
(polyExtents.GetWidth() > viewExtents.GetWidth() ) )
{
parcelPolys.HighlightSingle(element);
parcelLayer.ZoomToActiveElement();
parcelLayer.UnhighlightAllElements();
zoomChanged = 1;
}
else
zoomChanged = 0;
##################################################################
### re-enable redraw, redraw the view, and highlight the polygon
##################################################################
View.DisableRedraw = 0;
ViewRedraw(View);
parcelPolys.HighlightSingle(element);
prevScale = vwScale; # record view scale to check next time procedure is called
} # end else zoom setting has changed
} # end of DoZoom
#################################################################
### procedure to get owner name and address string for parcel
#################################################################
func string GetPropString (numeric propNum)
{
local string name$, num$, dir$, stname$, type$, aptnum$, sub$;
local string liststr$;
name$ = parcelVector.poly[propNum].ca062506.OWNER$;
num$ = parcelVector.poly[propNum].ca062506.SIT_ST_NUM$;
dir$ = parcelVector.poly[propNum].ca062506.SIT_ST_DIR$;
stname$ = parcelVector.poly[propNum].ca062506.SIT_ST_NAM$;
type$ = parcelVector.poly[propNum].ca062506.SIT_ST_TYP$;
#sub$ = parcelVector.poly[propNum].CA032904.SIT_ST_SUB$;
aptnum$ = parcelVector.poly[propNum].ca062506.SIT_APT_NU$;
liststr$ = sprintf( "%s: %s %s %s %s %s%s", name$, num$, dir$, stname$, type$, sub$, aptnum$ );
return liststr$;
} # end of GetPropString
#################################################################
### procedure called when search finds no matching parcel polygon
#################################################################
proc OnFoundNone ()
{
View.SetMessage(""); ### clear View window message and status bar (no redraw will occur
View.StatusBarClear(); ### to do this automatically)
View.NoBlankScreen = 1; ### don't redraw things that don't need to be redrawn
parcelLayer.UnhighlightAllElements(); ### unhighlight any currently highlighted parcel polygons
View.NoBlankScreen = 0;
viewProperty.SetEnabled(0); ### disable the View Property push-button
viewData.SetEnabled(0); ### disable the View Assessor's Website Data button
### update Search Result field in dialog
statusText.SetValue("No properties found matching these criteria", 0);
} # end of OnFoundNone
#####################################################################################
### procedure called when one or more property polygons meet the search criteria.
#####################################################################################
proc OnFound (numeric propCount)
{
if (propList.GetCount() > 0 ) then ### clear property list
propList.DeleteAllItems();
local string liststr$;
local numeric j, k, propNum;
for j = 1 to propCount
{
liststr$ = GetPropString(propsArray[j]); ### get name / address string for parcel
propList.AddItem(liststr$); ### add this string to the list
} # end of for j = 1 to propCount
if (propCount == 1) ### only one parcel polygon found
{
statusText.SetValue("One property found.", 0); ### update status field in dialog
propList.SetSelectedItemIndex(0); ### set the single list item to be selected
viewProperty.SetEnabled(0); ### disable the View Property push-button
viewData.SetEnabled(1); ### enable the View Assessor's Website Data button
propNum = propsArray[1];
parcelPolys.HighlightSingle(propNum); ### highlight element to make it active in view
DoZoom(propNum); ### pan / zoom to highlighted element
}
else ### more than one polygon found
{
View.NoBlankScreen = 1; ### don't redraw entire view
parcelLayer.UnhighlightAllElements(1); ### unhighlight any currently highlighted parcel polygon
View.NoblankScreen = 0;
statusText.SetValue( sprintf("%d properties found.", propCount) , 0); ### update status field in dialog
View.SetMessage(""); ## blank the View status message and bar
View.StatusBarClear();
viewProperty.SetEnabled(0); ### enable the View Property push-button
viewData.SetEnabled(0); ### enable the View Assessor's Website Data button
}
panels.SetActivePage(3); ### set Result List panel to be active (on top)
}
####################################################################
### procedure called when a property is selected in the Result List
####################################################################
proc OnPropListSelect ()
{
viewData.SetEnabled(1);
viewProperty.SetEnabled(1);
}
######################################################################################
### procedure called when the View Polygon button on the Result List panel is pressed.
######################################################################################
proc OnViewPoly ()
{
local numeric propNumber; # polyon element number of property selected from the Property List
### get the value from the property list (string) and convert to number (polygon element number)
propNumber = propsArray[propList.GetSelectedItemIndex() + 1];
View.DisableRedraw = 1;
parcelPolys.HighlightSingle(propNumber); ### highlight element to make it active in view
View.DisableRedraw = 0;
DoZoom(propNumber); ### pan / zoom to highlighted element
}
############################################################
### procedure called when View Assessor's Website Data
### button on dialog is pressed
############################################################
proc OnViewData ()
{
local numeric propNumber; # polyon element number of property selected from the Property List
local string url$;
### get the value from the property list (string) and convert to number (polygon element number)
propNumber = propsArray[propList.GetSelectedItemIndex() + 1];
url$ = parcelVector.poly[propNumber].ca062506.P_I_D$;
RunAssociatedApplication(url$);
}
#######################################################################
### procedure called to update status on dialog and view for new search
#######################################################################
proc OnNewSearch()
{
statusText.ClearValue(0); ## clear search status field on dialog
if (propList.GetCount() > 0) then
propList.DeleteAllItems(); ### clear property list
### Set message at bottom of View window
View.SetMessage("Searching for properties...");
}
#############################################################################
### procedure to get element numbers of polygons attached to matching records
### and take action depending on whether 0, 1, or >1 elements found
#############################################################################
proc GetPolygons ()
{
######################################################################
### We now have a list of records. Find the elements that have those
### records attached.
######################################################################
if (searchmode == 1) then
count = TableGetRecordListElementList(parcelVector.poly.ParcelAddress, matchRecList, count, propsArray);
else if (searchmode == 0) then
count = TableGetRecordListElementList(parcelVector.poly.OwnerName, matchRecList, count, propsArray);
if (count == 0) ### no properties found
{
OnFoundNone();
}
else ### one or more properties found
{
OnFound(count);
}
} # end of GetPolygons
#################################################################
# called when Search button on Property Search dialog is pressed
#################################################################
proc OnSearch ()
{
### get control settings (values) from dialog and store in GUI_FORMDATA
settings = dlgwin.GetValues();
local numeric possibleRecList[1];
local numeric numRecords, record;
#############################################
### address search; components of address are
### in separate fields in the database
#############################################
if (searchmode == 1)
{
##############################################
### declare local string variables for address
##############################################
local string addnum$; # address number as string
local string streetname$; # street name
local string prefix$; # street direction prefix (e.g. "S", "W")
local string prefixtext$; # text for street prefix in search text shown in dialog
local string streettype$; # street type (e.g. "ST", "RD");
local string streettypetext$; # text for street type in search text shown in dialog
local string fulladdress$; # full address
local numeric streetasnum; # number returned from street name string (0 if not numbered street)
#######################################
### read address values from formdata;
#######################################
### get address number and convert to string (to match database)
addnum$ = NumToStr( int( settings.GetValueNum("addnumfld") ) );
if (addnum$ == "0") then
addnum$ = "";
### get street direction prefix
prefix$ = settings.GetValueStr("comboPrefix");
if (prefix$ == "NONE") then
prefix$ = "";
### get street name and change to upper case (to match database);
### remove suffixes such as "nd" and "st" following the number
### in name of numbered street;
streetname$ = toupper$(settings.GetValueStr("streetnamefld") );
streetasnum = StrToNum(streetname$); # returns number at beginning of string or 0 if none
if ( streetasnum > 0) then
streetname$ = NumToStr(streetasnum); # convert street number back to string
### get street type setting
streettype$ = settings.GetValueStr("comboType");
###########################################################################################
### concatenate address components to full address string, omitting empty strings
##########################################################################################
if (prefix$ == "ANY") then
prefixtext$ = "\"Any\"";
else
prefixtext$ = prefix$;
if (streettype$ == "ANY") then
streettypetext$ = "\"Any\"";
else
streettypetext$ = streettype$;
if (prefix$ == "") then
fulladdress$ = sprintf("%s %s %s", addnum$, streetname$, streettypetext$);
else
fulladdress$ = sprintf("%s %s %s %s", addnum$, prefixtext$, streetname$, streettypetext$);
#########################################################
### don't search if no number and street name are entered
#########################################################
if ( (addnum$ == "") && (streetname$ == "") )
{
statusText.SetValue("Please enter an address number and street.", 0);
}
#################################################################################
### if full address is same as previous, abort search and reshow previous results
#################################################################################
else if ( (fulladdress$ == prevaddress$) && (prevsearchmode == 1) )
if (count == 0) then
OnFoundNone();
else
OnFound(count);
################################
### otherwise do address search
################################
else {
prevsearchmode = 1;
prevaddress$ = fulladdress$;
OnNewSearch();
searchText.SetValue(fulladdress$, 0);
###################################
### search through parcel polygons
###################################
count = 0; ### reinitialize polygon counter
ResizeArrayClear(matchRecList, 0); ### reinitialize array holding numbers of matching records
ResizeArrayClear(propsArray, 0); ### reinitialize array holding found polygon numbers
##############################################################################
### Narrow down the search from 99,000 records to just the records that
### match the requested SIT_ST_NUM value using a function that takes advantage
### of an index on the selected field to speed the search
##############################################################################
numRecords = TableKeyFieldLookupList(parcelVector.poly.ParcelAddress, "SIT_ST_NUM", addnum$, possibleRecList);
######################################################################
### search through the returned set of records for those that match all
### components of the requested address
######################################################################
for i = 1 to numRecords
{
View.SetStatusBar(i, numRecords); ### update View window's status bar
record = possibleRecList[i];
if ( (parcelVector.poly.ParcelAddress[@record].SIT_ST_NUM$ == addnum$) &&
(parcelVector.poly.ParcelAddress[@record].SIT_ST_NAM$ == streetname$) )
{
if ((prefix$ == "ANY") ||
(parcelVector.poly.ParcelAddress[@record].SIT_ST_DIR$ == prefix$) )
{
if ((streettype$ == "ANY") ||
(parcelVector.poly.ParcelAddress[@record].SIT_ST_TYP$ == streettype$))
{
count = count + 1;
ResizeArrayPreserve(matchRecList, count + 1); ### increase array size for next polygon found
matchRecList[count] = record; ### add polygon number to array
}
}
}
}
### call procedure to get polygons corresponding to matching records
GetPolygons();
} # end else [new search]
} # end if (searchmode == 1)
####################################################################
### owner name search; entire name(s) is in single field in database
####################################################################
else if (searchmode == 0)
{
# string variables for owner name components from form
local string lastname$, firstname$, middle$;
local string firstmid$; # concatenation of first name and middle initial
local string fullname$; # full name string (last, firstmid)
local numeric firstmidlength; # length of concatenated first name / middle initial
local numeric numTokens; # number of tokens in owner name (delimited by space)
local numeric j; # counter for looping through tokens in name
local numeric name_in; # flag indicating entered first name / middle initial begins one of the name tokens
local class STRINGLIST tokenList; # stringlist containing tokens from name
############################################################
### read name values from formdata and set all to upper case
############################################################
lastname$ = toupper$(settings.GetValueStr("lastnamefld") );
firstname$ = toupper$(settings.GetValueStr("firstnamefld") );
middle$ = toupper$(settings.GetValueStr("midintfld") );
### concatenate middle initial with first name
if (middle$ <> "") then
firstmid$ = sprintf("%s %s", firstname$, middle$);
else
firstmid$ = firstname$;
firstmidlength = strlen(firstmid$); ### get length of string to use later in search
### concatenate lastname and firstmid to use to display search text
fullname$ = sprintf("%s, %s", lastname$, firstmid$);
######################################################
### don't search if no owner name is entered in dialog
######################################################
if (fullname$ == ", ")
{
statusText.SetValue("Please enter an owner name.", 0);
}
#######################################################################
### if name is same as previous, abort search and show previous results
#######################################################################
else if ( (fullname$ == prevname$) && (prevsearchmode == 0) )
if (count == 0) then
OnFoundNone();
else
OnFound(count);
#############################
### otherwise do new search
#############################
else
{
prevsearchmode = 0;
### record name string for comparison on next search if result was multiple
prevname$ = fullname$;
searchText.SetValue(fullname$, 0);
OnNewSearch();
####################################
### search through parcel polygons
####################################
count = 0; ### reinitialize polygon counter
ResizeArrayClear(matchRecList, 0); ### reinitialize array holding numbers of matching records
ResizeArrayClear(propsArray, 0); ### reinitialize array holding found polygon numbers;
###############################################################################
### Narrow down the search from 99,000 records to just the records in which
### the OWNER string begins with the requested last name. Uses a function
### that takes advantage of an index on the selected field to speed the search
###############################################################################
numRecords = TableKeyFieldLookupList(parcelVector.poly.OwnerName, "OWNER", lastname$, possibleRecList, "StartsWith" );
###########################################################################
### Now search the returned records for those with a match to the
### requested name
###########################################################################
for i = 1 to numRecords
{
local numeric name_in = 0;
View.SetStatusBar(i, numRecords); ### update View window's status bar
record = possibleRecList[i];
### get owner name string from database
local string name$ = parcelVector.poly.OwnerName[@record].OWNER$;
local class STRING teststr$;
if ( GetToken(name$, ",", 1) == lastname$) ### check for exact match with last name (not just starts with)
{
numTokens = NumberTokens(name$, ",&"); ### number of tokens in owner name with "," and "&" as delimiters
for j = 2 to numTokens ### loop through tokens following last name
{
teststr$ = GetToken(name$, ",&", j);
teststr$.remove(0, 0); ### remove leading space from test string
if ( left$( teststr$, firstmidlength) == firstmid$) then
name_in = 1;
}
}
if (name_in == 1)
{
count = count + 1;
ResizeArrayPreserve(matchRecList, count + 1); ### increase array size for next polygon found
matchRecList[count] = record; ### add polygon number to array
}
}
### call procedure to get polygons corresponding to matching records
GetPolygons();
} # end else do new search
} # end else if (searchmode == 0)
} # end OnSearch
###################################################################
### called when the Property Search dialog is closed by the Cancel,
### OK, or X Windows "X" button
###################################################################
proc OnClose()
{
dlgwin.Close(1);
View.SetDefaultTool(); # switch to default tool on the View tool bar
}