Differences

This shows you the differences between two versions of the page.

Link to this comparison view

google_maps [2012/04/02 16:11]
srdjan.lukovic [GUI Code]
google_maps [2012/07/09 10:56] (current)
srdjan.lukovic [GUI Code]
Line 1: Line 1:
-====== Google Maps Sample ====== +====== Interactive Maps ====== 
-This sample application fully embeds Google Maps. This is example of how complex external components can be integrated with SOLoist code. You can browse map just as you would on original application. By choosing //House// from suggest-box map view will be centered on location based on the saved coordinates. You can unlock marker and choose different location, all data will be automatically saved. You could also type in address manually and perform geocodingexact coordinates will be provided by google maps+ 
 +**Interactive Maps** is a [[SOLoist Sample Applications|SOLoist sample application]] that fully embeds [[http://maps.google.com/ | Google Maps]] that interact with the enclosing application by exhanging geo-coordinates. This example demonstrates how complex external components can be integrated with SOLoist code in order to interchange the data and keep them in sync 
 + 
 +The user can browse the map. By selecting an object of //House// in the suggest box, the map view will be positioned on the location based on the coordinates stored in the object's //coordinates// attribute 
 + 
 +When the marker is unlocked by unchecking the checkbox, and different location is selected in the map, all the data from Google Maps will be automatically saved to the selected object's attributes 
 + 
 +The user can also type in an address in the text input fieldwhen Google Maps provides the coordinates
 + 
 +This way, the geo-coordinates from Google Maps and the values of attributes from SOLoist objects are kept in sync
  
 ==== Live example ==== ==== Live example ====
Line 6: Line 15:
 [[http://soloistdemo.org/SampleApplications/gmaps.html]]\\ [[http://soloistdemo.org/SampleApplications/gmaps.html]]\\
 [[http://soloistdemo.org/SampleApplications/oql?q=SELECT+h%2C+h.code%2C+h.address%2C+h.city%2C+h.country%2C+h.coordinates%0D%0AFROM+House+h&f=html | OQL Query: Houses]] [[http://soloistdemo.org/SampleApplications/oql?q=SELECT+h%2C+h.code%2C+h.address%2C+h.city%2C+h.country%2C+h.coordinates%0D%0AFROM+House+h&f=html | OQL Query: Houses]]
 +|{{screen:googlemaps.png?300}}|
  
 ===== UML Model ===== ===== UML Model =====
Line 11: Line 21:
  
 ===== Business Logic Code ===== ===== Business Logic Code =====
 +None.
 +
 +===== GUI Code =====
 <code java> <code java>
-//...+package rs.sol.sampleapps.gmaps; 
 + 
 +import rs.sol.sampleapps.House; 
 +import rs.sol.soloist.server.guiconfiguration.components.GUIHTMLComponent; 
 +import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent; 
 +import rs.sol.soloist.server.guiconfiguration.components.GUIPanelComponent; 
 +import rs.sol.soloist.server.guiconfiguration.construction.GUIComponentBinding; 
 +import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIEdit; 
 +import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIInput; 
 +import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIFindAllInstancesSAPComponent; 
 +import rs.sol.soloist.server.uml.concepts.runtime.ISlot; 
 + 
 +public class GoogleMapsFragment { 
 + 
 + private ISlot<?> house; 
 + private GUIPanelComponent rootPanel; 
 + 
 + public GoogleMapsFragment(GUIPanelComponent rootPanel) { 
 + this.rootPanel = rootPanel; 
 + this.house = rootPanel.opRelay1(); 
 + init(); 
 +
 + 
 + private void init() { 
 + houseLocationDetails(); 
 +  
 + GUIEdit coordinates = GUIEdit.createField(rootPanel, House.PROPERTIES.coordinates); 
 + GUIComponentBinding.create(house, coordinates.ipElement()); 
 + coordinates.setStyle("#coordinatesH"); 
 + GUIHTMLComponent.create(rootPanel, "<div id=\"map_canvasH\"></div>"); 
 + 
 + GUIHTMLComponent html1 = GUIHTMLComponent.create(rootPanel, ""); 
 + html1.setStyle("#tab1886H"); 
 +  
 + GUIComponentBinding.create(house, html1.ipHTML()); 
 +
 + 
 + private void houseLocationDetails() { 
 + GUIPanelComponent table = GUIPanelComponent.createTable(rootPanel); 
 + table.setStyle("form"); 
 +  
 + int row = 0, col = 0; 
 + GUILabelComponent.create(table, "House", row, col++).setStyle("formLabel"); 
 + GUILabelComponent.create(table, "Address", row, col++).setStyle("formLabel"); 
 + GUILabelComponent.create(table, "City", row, col++).setStyle("formLabel"); 
 + GUILabelComponent.create(table, "Country", row, col++).setStyle("formLabel"); 
 +  
 + GUIFindAllInstancesSAPComponent allHouses = GUIFindAllInstancesSAPComponent.create(rootPanel, House.CLASSIFIER); 
 + GUIInput suggestBox = GUIInput.createSuggest(table); 
 + GUIComponentBinding.create(allHouses.opValue(), suggestBox.ipCollection()); 
 +  
 + GUIEdit seAddress = GUIEdit.createField(table, House.PROPERTIES.address); 
 + GUIComponentBinding.create(house, seAddress.ipElement()); 
 + seAddress.setStyle("#addressH"); 
 +  
 + GUIEdit seCity = GUIEdit.createField(table, House.PROPERTIES.city); 
 + GUIComponentBinding.create(house, seCity.ipElement()); 
 + seCity.setStyle("#cityH"); 
 + 
 + GUIEdit seCountry = GUIEdit.createField(table, House.PROPERTIES.country); 
 + GUIComponentBinding.create(house, seCountry.ipElement()); 
 + seCountry.setStyle("#countryH"); 
 +  
 + row++; col = 0; 
 + suggestBox.setRowColumn(row, col++); 
 + seAddress.setRowColumn(row, col++); 
 + seCity.setRowColumn(row, col++); 
 + seCountry.setRowColumn(row, col++); 
 +  
 + GUIComponentBinding.create(suggestBox.opValue(), rootPanel.ipRelay1()); 
 +
 +  
 +}
 </code> </code>
  
-===== GUI Code ===== 
 <code java> <code java>
 package rs.sol.sampleapps.gmaps; package rs.sol.sampleapps.gmaps;
Line 23: Line 107:
 import rs.sol.soloist.helpers.init.Initializer; import rs.sol.soloist.helpers.init.Initializer;
 import rs.sol.soloist.helpers.init.InitializerFailedException; import rs.sol.soloist.helpers.init.InitializerFailedException;
-import rs.sol.soloist.server.builtindomains.builtindatatypes.Text; 
 import rs.sol.soloist.server.guiconfiguration.components.GUIApplicationComponent; import rs.sol.soloist.server.guiconfiguration.components.GUIApplicationComponent;
 import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent; import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent;
Line 39: Line 122:
  public void init() throws InitializerFailedException {  public void init() throws InitializerFailedException {
  GUIApplicationComponent application = new GUIApplicationComponent();  GUIApplicationComponent application = new GUIApplicationComponent();
- application.name.set(Text.fromString("GMapsSample"));+ application.setName("GMapsSample");
  SoloistServiceServlet.registerApplication(application);  SoloistServiceServlet.registerApplication(application);
- application.context.set(createContextAndStyles());+ application.setContext(createContextAndStyles());
   
  GUIPanelComponent root = GUIPanelComponent.createFlow(application);  GUIPanelComponent root = GUIPanelComponent.createFlow(application);
   
  GUILabelComponent title = GUILabelComponent.create(root, "Google Maps");  GUILabelComponent title = GUILabelComponent.create(root, "Google Maps");
- title.styleName.set(Text.fromString("titleStyle"));+ title.setStyle("titleStyle");
   
  GUIPanelComponent topPanel = GUIPanelComponent.createFlow(root);  GUIPanelComponent topPanel = GUIPanelComponent.createFlow(root);
- topPanel.styleName.set(Text.fromString("topPanel"));+ topPanel.setStyle("topPanel");
  
  new GoogleMapsFragment(topPanel);  new GoogleMapsFragment(topPanel);
Line 56: Line 139:
  private GUIContext createContextAndStyles() {  private GUIContext createContextAndStyles() {
  GUIContext context = new GUIContext();  GUIContext context = new GUIContext();
- context.supercontext.set(DefaultContextInit.getRoot());+ DefaultContextInit.getRoot().addContext(context);
  
  GUIObjectSetting person = GUIObjectSetting.create(context, House.CLASSIFIER);  GUIObjectSetting person = GUIObjectSetting.create(context, House.CLASSIFIER);
Line 65: Line 148:
  
 } }
 +</code>
  
 +<code javascript extension.js>
 +/**
 + * Javascript that controls behavior of external components.
 + */
 +
 +var mapH, markerH, positionH;
 +var geocoder;
 +var timeout = 100;
 +var lock = true;
 +var first = true;
 +
 +var solHQ = new google.maps.LatLng(44.813209013839284, 20.464512819311494);
 +var lockText = 'Lock marker';
 +var coorText = 'Coordinates';
 +var buttonText = 'Geocode';
 +
 +function initialize() {
 +
 + geocoder = new google.maps.Geocoder();
 + markerH = new google.maps.Marker();
 +
 + var myOptions = {
 + zoom : 14,
 + center : solHQ,
 + scaleControl : true,
 + mapTypeId : google.maps.MapTypeId.ROADMAP
 + };
 +
 + var canvasId = "map_canvasH";
 + var coorId = "coordinatesH";
 +
 + mapH = new google.maps.Map(document.getElementById(canvasId), myOptions);
 + positionH = coordinatesControl(mapH);
 +
 + geocode(mapH);
 + lockMarkerControl(mapH);
 +
 + google.maps.event.addListener(mapH, 'click', function(event) {
 + if (!lock) {
 + var coor = document.getElementById(coorId);
 + markerH.setPosition(event.latLng);
 + markerH.setMap(mapH);
 + coor.value = event.latLng;
 + positionH.innerHTML = parseLatLng(event.latLng);
 + var address = document.getElementById("addressH");
 + var city = document.getElementById("cityH");
 + var country = document.getElementById("countryH");
 + codeLatLng(event.latLng, address, city, country);
 + coor.focus();
 + coor.blur();
 + }
 + });
 +
 + drawMap();
 +
 +}
 +
 +function codeLatLng(latlng, address, city, country) {
 + geocoder.geocode({
 + 'latLng' : latlng
 + }, function(results, status) {
 + if (status == google.maps.GeocoderStatus.OK) {
 + if (results[0]) {
 + var ac = results[0].address_components;
 + var str = "", num = "", cty = "", cnt = "";
 + for ( var i in ac) {
 + if (ac[i].types[0] == "street_number")
 + num = ac[i].long_name;
 + if (ac[i].types[0] == "street_address" || ac[i].types[0] == "route" || ac[i].types[0] == "intersection")
 + str = ac[i].long_name;
 + if (ac[i].types[0] == "locality")
 + cty = ac[i].long_name;
 + if (ac[i].types[0] == "country")
 + cnt = ac[i].long_name;
 + }
 + address.value = str + " " + num;
 + city.value = cty;
 + country.value = cnt;
 + address.focus();
 + address.blur();
 + city.focus();
 + city.blur();
 + country.focus();
 + country.blur();
 + }
 + } else {
 + alert("Geocoder failed due to: " + status);
 + }
 + });
 +}
 +
 +function codeAddress(address, coor) {
 + geocoder.geocode({
 + 'address' : address
 + }, function(results, status) {
 + if (status == google.maps.GeocoderStatus.OK) {
 + coor.value = results[0].geometry.location;
 + coor.focus();
 + coor.blur();
 + drawMap();
 + }
 + });
 +}
 +
 +function parseLatLng(latLng) {
 + if (latLng === "")
 + return coorText + " ( - )";
 +
 + var dec = 1000000;
 + var ll = new Array();
 + ll = latLng.toString().substring(1, latLng.toString().length - 1).split(', ');
 + return coorText + " (" + (Math.round(parseFloat(ll[0]) * dec) / dec) + ", "
 + + (Math.round(parseFloat(ll[1]) * dec) / dec) + ")";
 +}
 +
 +function coordinatesControl(map) {
 + var controlDiv = document.createElement('DIV');
 + controlDiv.id = 'mapsCoor';
 + map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
 + return controlDiv;
 +}
 +
 +function geocode(map) {
 + var button = document.createElement('button');
 + button.id = 'geocodeButton';
 + button.innerHTML = buttonText;
 +
 + map.controls[google.maps.ControlPosition.TOP_RIGHT].push(button);
 +
 + var address = document.getElementById("addressH");
 + var city = document.getElementById("cityH");
 + var country = document.getElementById("countryH");
 +
 + google.maps.event.addDomListener(button, 'click', function() {
 + var fullAddress = address.value + ' ' + city.value + ' ' + country.value;
 + var coor = document.getElementById("coordinatesH");
 + codeAddress(fullAddress, coor);
 + });
 +}
 +
 +function lockMarkerControl(map) {
 + var controlDiv = document.createElement('DIV');
 + controlDiv.id = 'mapsCheckbox';
 + var cb = document.createElement('input');
 + cb.type = 'checkbox';
 + cb.checked = lock;
 + controlDiv.innerHTML = '<div id=\'text\'>' + lockText + '</div>';
 + controlDiv.appendChild(cb);
 +
 + map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv);
 +
 + google.maps.event.addDomListener(cb, 'click', function() {
 + lock = cb.checked;
 + });
 +}
 +
 +function drawMap() {
 +
 + var coor = document.getElementById("coordinatesH");
 + if (coor != null && coor.value !== "") {
 + var latLng = new Array();
 + latLng = coor.value.substring(1, coor.value.length - 1).split(', ');
 + position = new google.maps.LatLng(latLng[0], latLng[1]);
 + markerH.setMap(mapH);
 + markerH.setPosition(position);
 + mapH.setCenter(position);
 + positionH.innerHTML = parseLatLng(position);
 + } else {
 + mapH.setCenter(solHQ);
 + markerH.setMap(null);
 + positionH.innerHTML = parseLatLng("");
 + }
 +}
 +
 +function htmlComponentChanged(id) {
 +
 + if (id == "tab1886H") {
 + if (first) {
 + setTimeout(function() {
 + initialize();
 + }, timeout);
 + first = false;
 + } else {
 + setTimeout(function() {
 + drawMap();
 + }, timeout);
 + }
 + }
 +}
 </code> </code>
Print/export