/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sun Microsystems nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package localsearch;
import java.io.InputStream;
import java.lang.Exception;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.io.http.HttpRequest;
import javafx.lang.FX;
import javafx.scene.control.TextBox;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.LayoutInfo;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import localsearch.model.Restaurant;
import localsearch.parser.JSONPullParser;
import localsearch.parser.XMLPullParser;
import localsearch.RequestHandler;
import localsearch.view.ImageButton;
def dataType = "xml";
var stageDragInitialX:Number;
var stageDragInitialY:Number;
def appid = FX.getArgument("yahoo_appid");
var sceneWidth : Number = bind scene.width;
var sceneHeight : Number = bind scene.height;
var index:Integer = 0;
public var restaurants: Restaurant[];
public function searchCoffeeShops(zipcode:String) : Void {
index = 0;
delete restaurants;
resetRestaurantDetails();
if(not validateZipCode(zipcode)) {
alert("Error", "Zip Code {zipcode} is not valid. Enter valid zip code.");
return;
}
def query = "coffee";
def results = 5;
def location = "http:;
var resultsProcessor: function(is: InputStream) : Void;
if("xml".equalsIgnoreCase(dataType)) {
resultsProcessor = XMLPullParser.processResults;
} else {
resultsProcessor = JSONPullParser.processResults;
}
println("Loading {dataType} data from {location}...\"");
alert("Please wait...", "Searching for Coffee Shops near zip code: {zipcode}...");
try {
var request = RequestHandler {
location: location
method: HttpRequest.GET
processResults: resultsProcessor
}
request.start();
} catch (e:Exception) {
println("WARNING: {e}");
alert("Error", "Could not search... Please try again later.");
}
}
function validateZipCode(zipcode:String): Boolean {
try {
if(zipcode.length() == 5) {
var zipCodeInt = java.lang.Integer.valueOf(zipcode).intValue();
return (zipCodeInt > 0);
} else if (zipcode.length() == 10) {
var dashIndex = zipcode.indexOf("-");
if(dashIndex != 5) return false;
var firstPart = zipcode.substring(0, dashIndex);
var zipCodeInt = java.lang.Integer.valueOf(firstPart).intValue();
if(zipCodeInt <= 0) { return false; }
var secondPart = zipcode.substring(0, dashIndex);
zipCodeInt = java.lang.Integer.valueOf(secondPart).intValue();
return (zipCodeInt > 0);
}
} catch (e:Exception) { }
return false;
}
function getBGImage(width:Integer, height:Integer) : Image {
var bounds = "{width}X{height}";
if(bounds.equals("240X320") or bounds.equals("240X400") or
bounds.equals("320X240") or bounds.equals("400X240")) {
return Image {
url: "{__DIR__}images/background_{width}X{height}.png"
}
} else {
return null;
}
}
var bgImage:ImageView = ImageView {
focusTraversable: true
image: bind getBGImage(sceneWidth, sceneHeight)
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_LEFT) {
onBack();
} else if(e.code == KeyCode.VK_RIGHT) {
onNext();
} else if(e.code == KeyCode.VK_DOWN) {
zipCodeText.requestFocus();
}
}
onMouseClicked:function(e:MouseEvent) {
bgImage.requestFocus();
}
}
var backButton = ImageButton {
x: 3
y: bind (sceneHeight/2.0 - 10)
normalImage: Image { url: "{__DIR__}images/arrow_left_normal.png" }
overImage: Image { url: "{__DIR__}images/arrow_left_over.png" }
onMouseClicked: function(e) {
onBack();
}
}
function onBack() : Void {
if((sizeof restaurants) == 0) { return; }
index--; if(index < 0) { index = ((sizeof restaurants) - 1); }
showRestaurantDetails(index, false);
}
var nextButton = ImageButton {
x: bind (sceneWidth - 19)
y: bind (sceneHeight/2.0 - 10)
normalImage: Image { url: "{__DIR__}images/arrow_right_normal.png" }
overImage: Image { url: "{__DIR__}images/arrow_right_over.png" }
onMouseClicked: function(e) {
onNext();
}
}
function onNext() : Void {
if((sizeof restaurants) == 0) { return; }
index++; if(index >= (sizeof restaurants)) { index = 0; }
showRestaurantDetails(index, true);
}
var closeButton = ImageButton {
x: bind (sceneWidth - 20)
y: 8
normalImage: Image { url: "{__DIR__}images/x_normal.png" }
overImage: Image { url: "{__DIR__}images/x_over.png" }
visible: bind ("{__PROFILE__}" != "browser")
onMouseClicked: function(e) {
javafx.lang.FX.exit();
}
}
public function resetRestaurantDetails() : Void {
shopName = "";
address = "";
city = "";
phone = "";
star.visible = false;
comments = "";
title = "Nearest Coffee Shops";
}
public function showRestaurantDetails(index:Integer, scrollLeft:Boolean) : Void {
if(index >= (sizeof restaurants)) { return ; }
var scrollXVal = 1;
if(scrollLeft) { scrollXVal = -1; }
shopDetailsX = 0;
var timeline:Timeline = Timeline {
repeatCount:1
autoReverse: false
rate: 1.0
keyFrames: [
KeyFrame {
time: 250ms
values: [ shopDetailsX => scrollXVal * sceneWidth tween Interpolator.LINEAR ]
action: function() {
shopDetailsX = scrollXVal * -sceneWidth;
var result = restaurants[index];
shopName = trimString(result.title, 25);
address = trimString(result.address, 30);
city = trimString("{result.city} {result.state}", 30);
phone = "{result.phone}";
setStars(result.rating.averageRating);
var lastReview = "{result.rating.lastReviewIntro}";
comments = trimString("{lastReview}", 300);
title = "Coffee Shops ({index + 1} of {sizeof restaurants})";
bgImage.requestFocus();
}
},
KeyFrame {
time: 250ms
values: [ shopDetailsX => scrollXVal * -sceneWidth tween Interpolator.DISCRETE ]
},
KeyFrame {
time: 500ms
values: [ shopDetailsX => 0 tween Interpolator.LINEAR ]
}
]
};
timeline.playFromStart();
}
function trimString(string:String, length:Integer) : String {
if(string == null) return "";
if(string.length() > length) {
return "{string.substring(0, length).trim()}...";
} else {
return string;
}
}
var defaultStarImage = Image {
url: "{__DIR__}images/star0.png"
}
var star = ImageView {
x: 25
y: 111
image: defaultStarImage
visible: false
}
function setStars(starCount:String) : Void {
var imageSuffix = "0";
try {
var starIntCount = java.lang.Float.valueOf(starCount).intValue();
imageSuffix = "{starIntCount}";
if(starIntCount > 5) {
imageSuffix = "5";
} else if(starCount.indexOf(".") > 0) {
imageSuffix = "{imageSuffix}.5";
}
} catch (e:java.lang.Exception) {
}
star.image = Image {
url: "{__DIR__}images/star{imageSuffix}.png"
placeholder: defaultStarImage
}
star.visible = true;
}
var titleBar = Rectangle {
width: bind sceneWidth
height: 25
fill: Color.TRANSPARENT
visible: bind ("{__PROFILE__}" != "browser")
onMousePressed: function(e) {
stageDragInitialX = e.screenX - stage.x;
stageDragInitialY = e.screenY - stage.y;
}
onMouseDragged: function(e) {
stage.x = e.screenX - stageDragInitialX;
stage.y = e.screenY - stageDragInitialY;
}
}
var title = "Nearest Coffee Shops";
var titleText : Text = Text {
translateX: bind (sceneWidth - titleText.boundsInLocal.width)/2.0
y: 18
font: Font { name:"sansserif", size: 14 }
fill: Color.BLACK
content: bind title
}
var divider = Line {
startX: 0 startY: 25
endX: bind sceneWidth endY: 25
stroke: Color.rgb(138, 110, 72)
}
var shopName = "";
var shopNameText = Text {
x: 25
y: 50
font: Font { name:"sansserif", size: 13 }
fill: Color.BLACK
content: bind shopName
}
var address = "";
var addressText = Text {
x: 25
y: 68
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind address
}
var city = "";
var cityText = Text {
x: 25
y: 86
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind city
}
var phone = "";
var phoneText = Text {
x: 25
y: 104
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind phone
}
var comments = "";
var commentsText = Text {
x: 25
y: 130
font: Font { name:"sansserif", size: 11 }
fill: Color.BLACK
content: bind comments
wrappingWidth: bind (sceneWidth - 60)
textOrigin: TextOrigin.TOP
clip: Rectangle {
x: 23 y: 130
width: bind sceneWidth
height: bind (zipSearchPanel.translateY - 137)
}
};
var shopDetailsX: Number = 0;
var shopDetailsDisplay = Group {
content: bind [
shopNameText, addressText, cityText, phoneText, commentsText, star
]
translateX: bind shopDetailsX
}
var shopDetailsGroup = Group {
content: [ shopDetailsDisplay ]
clip: Rectangle {
x: 15
y: 32
width: bind (sceneWidth - 30)
height: bind (sceneHeight - 64)
}
}
var zipCodeLabel = Text {
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: "zip code:"
textOrigin: TextOrigin.TOP
layoutInfo: LayoutInfo { vpos: javafx.geometry.VPos.CENTER }
}
var zipCodeText: TextBox = TextBox {
blocksMouse: true
columns: 7
selectOnFocus: false
text: "95054"
action: function() {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
}
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_UP) {
bgImage.requestFocus();
} else if(e.code == KeyCode.VK_RIGHT) {
if("{__PROFILE__}" == "mobile") {
searchButton.requestFocus();
}
}
}
}
var searchButton = ImageButton {
y: 2
normalImage: Image { url: "{__DIR__}images/search_normal.png" };
overImage: Image { url: "{__DIR__}images/search_over.png" };
focusImage: Image { url: "{__DIR__}images/search_focus.png" };
onMouseClicked: function(e) {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
}
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_ENTER) {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
} else if(e.code == KeyCode.VK_UP) {
bgImage.requestFocus();
} else if(e.code == KeyCode.VK_LEFT) {
zipCodeText.requestFocus();
}
}
}
var zipSearchPanel : HBox = HBox {
translateX: bind (sceneWidth - zipSearchPanel.boundsInLocal.width)/2.0
translateY: bind (sceneHeight - 52)
content: [zipCodeLabel, zipCodeText, searchButton]
spacing: 10
};
var serviceProviderText : Text = Text {
translateX: bind (sceneWidth - serviceProviderText.boundsInLocal.width)/2.0
y: bind (sceneHeight - 10)
font: Font { name:"sansserif", size: 11 }
fill: Color.rgb(96, 78, 51)
content: "Web Services by Yahoo!"
}
var scene : Scene = Scene {
content: Group {
content: bind [
bgImage, titleBar, titleText, divider, shopDetailsGroup, backButton, nextButton, closeButton,
zipSearchPanel, serviceProviderText
]
clip: Rectangle {
width: bind sceneWidth
height: bind sceneHeight
arcWidth: 20
arcHeight: 20
}
}
fill: Color.TRANSPARENT
}
var stage : Stage = Stage {
title: "Coffee Shop Search"
resizable: false
style: StageStyle.TRANSPARENT
scene: bind scene
width: 240
height: 320
}
public function alert(alertTitle:String, msg:String): Void {
println(msg);
phone = alertTitle;
comments = trimString(msg, 240);
}
function run() {
searchCoffeeShops("95054");
}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sun Microsystems nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package localsearch;
import java.io.InputStream;
import java.lang.Exception;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.io.http.HttpRequest;
import javafx.lang.FX;
import javafx.scene.control.TextBox;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.LayoutInfo;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import localsearch.model.Restaurant;
import localsearch.parser.JSONPullParser;
import localsearch.parser.XMLPullParser;
import localsearch.RequestHandler;
import localsearch.view.ImageButton;
def dataType = "xml";
var stageDragInitialX:Number;
var stageDragInitialY:Number;
def appid = FX.getArgument("yahoo_appid");
var sceneWidth : Number = bind scene.width;
var sceneHeight : Number = bind scene.height;
var index:Integer = 0;
public var restaurants: Restaurant[];
public function searchCoffeeShops(zipcode:String) : Void {
index = 0;
delete restaurants;
resetRestaurantDetails();
if(not validateZipCode(zipcode)) {
alert("Error", "Zip Code {zipcode} is not valid. Enter valid zip code.");
return;
}
def query = "coffee";
def results = 5;
def location = "http:;
var resultsProcessor: function(is: InputStream) : Void;
if("xml".equalsIgnoreCase(dataType)) {
resultsProcessor = XMLPullParser.processResults;
} else {
resultsProcessor = JSONPullParser.processResults;
}
println("Loading {dataType} data from {location}...\"");
alert("Please wait...", "Searching for Coffee Shops near zip code: {zipcode}...");
try {
var request = RequestHandler {
location: location
method: HttpRequest.GET
processResults: resultsProcessor
}
request.start();
} catch (e:Exception) {
println("WARNING: {e}");
alert("Error", "Could not search... Please try again later.");
}
}
function validateZipCode(zipcode:String): Boolean {
try {
if(zipcode.length() == 5) {
var zipCodeInt = java.lang.Integer.valueOf(zipcode).intValue();
return (zipCodeInt > 0);
} else if (zipcode.length() == 10) {
var dashIndex = zipcode.indexOf("-");
if(dashIndex != 5) return false;
var firstPart = zipcode.substring(0, dashIndex);
var zipCodeInt = java.lang.Integer.valueOf(firstPart).intValue();
if(zipCodeInt <= 0) { return false; }
var secondPart = zipcode.substring(0, dashIndex);
zipCodeInt = java.lang.Integer.valueOf(secondPart).intValue();
return (zipCodeInt > 0);
}
} catch (e:Exception) { }
return false;
}
function getBGImage(width:Integer, height:Integer) : Image {
var bounds = "{width}X{height}";
if(bounds.equals("240X320") or bounds.equals("240X400") or
bounds.equals("320X240") or bounds.equals("400X240")) {
return Image {
url: "{__DIR__}images/background_{width}X{height}.png"
}
} else {
return null;
}
}
var bgImage:ImageView = ImageView {
focusTraversable: true
image: bind getBGImage(sceneWidth, sceneHeight)
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_LEFT) {
onBack();
} else if(e.code == KeyCode.VK_RIGHT) {
onNext();
} else if(e.code == KeyCode.VK_DOWN) {
zipCodeText.requestFocus();
}
}
onMouseClicked:function(e:MouseEvent) {
bgImage.requestFocus();
}
}
var backButton = ImageButton {
x: 3
y: bind (sceneHeight/2.0 - 10)
normalImage: Image { url: "{__DIR__}images/arrow_left_normal.png" }
overImage: Image { url: "{__DIR__}images/arrow_left_over.png" }
onMouseClicked: function(e) {
onBack();
}
}
function onBack() : Void {
if((sizeof restaurants) == 0) { return; }
index--; if(index < 0) { index = ((sizeof restaurants) - 1); }
showRestaurantDetails(index, false);
}
var nextButton = ImageButton {
x: bind (sceneWidth - 19)
y: bind (sceneHeight/2.0 - 10)
normalImage: Image { url: "{__DIR__}images/arrow_right_normal.png" }
overImage: Image { url: "{__DIR__}images/arrow_right_over.png" }
onMouseClicked: function(e) {
onNext();
}
}
function onNext() : Void {
if((sizeof restaurants) == 0) { return; }
index++; if(index >= (sizeof restaurants)) { index = 0; }
showRestaurantDetails(index, true);
}
var closeButton = ImageButton {
x: bind (sceneWidth - 20)
y: 8
normalImage: Image { url: "{__DIR__}images/x_normal.png" }
overImage: Image { url: "{__DIR__}images/x_over.png" }
visible: bind ("{__PROFILE__}" != "browser")
onMouseClicked: function(e) {
javafx.lang.FX.exit();
}
}
public function resetRestaurantDetails() : Void {
shopName = "";
address = "";
city = "";
phone = "";
star.visible = false;
comments = "";
title = "Nearest Coffee Shops";
}
public function showRestaurantDetails(index:Integer, scrollLeft:Boolean) : Void {
if(index >= (sizeof restaurants)) { return ; }
var scrollXVal = 1;
if(scrollLeft) { scrollXVal = -1; }
shopDetailsX = 0;
var timeline:Timeline = Timeline {
repeatCount:1
autoReverse: false
rate: 1.0
keyFrames: [
KeyFrame {
time: 250ms
values: [ shopDetailsX => scrollXVal * sceneWidth tween Interpolator.LINEAR ]
action: function() {
shopDetailsX = scrollXVal * -sceneWidth;
var result = restaurants[index];
shopName = trimString(result.title, 25);
address = trimString(result.address, 30);
city = trimString("{result.city} {result.state}", 30);
phone = "{result.phone}";
setStars(result.rating.averageRating);
var lastReview = "{result.rating.lastReviewIntro}";
comments = trimString("{lastReview}", 300);
title = "Coffee Shops ({index + 1} of {sizeof restaurants})";
bgImage.requestFocus();
}
},
KeyFrame {
time: 250ms
values: [ shopDetailsX => scrollXVal * -sceneWidth tween Interpolator.DISCRETE ]
},
KeyFrame {
time: 500ms
values: [ shopDetailsX => 0 tween Interpolator.LINEAR ]
}
]
};
timeline.playFromStart();
}
function trimString(string:String, length:Integer) : String {
if(string == null) return "";
if(string.length() > length) {
return "{string.substring(0, length).trim()}...";
} else {
return string;
}
}
var defaultStarImage = Image {
url: "{__DIR__}images/star0.png"
}
var star = ImageView {
x: 25
y: 111
image: defaultStarImage
visible: false
}
function setStars(starCount:String) : Void {
var imageSuffix = "0";
try {
var starIntCount = java.lang.Float.valueOf(starCount).intValue();
imageSuffix = "{starIntCount}";
if(starIntCount > 5) {
imageSuffix = "5";
} else if(starCount.indexOf(".") > 0) {
imageSuffix = "{imageSuffix}.5";
}
} catch (e:java.lang.Exception) {
}
star.image = Image {
url: "{__DIR__}images/star{imageSuffix}.png"
placeholder: defaultStarImage
}
star.visible = true;
}
var titleBar = Rectangle {
width: bind sceneWidth
height: 25
fill: Color.TRANSPARENT
visible: bind ("{__PROFILE__}" != "browser")
onMousePressed: function(e) {
stageDragInitialX = e.screenX - stage.x;
stageDragInitialY = e.screenY - stage.y;
}
onMouseDragged: function(e) {
stage.x = e.screenX - stageDragInitialX;
stage.y = e.screenY - stageDragInitialY;
}
}
var title = "Nearest Coffee Shops";
var titleText : Text = Text {
translateX: bind (sceneWidth - titleText.boundsInLocal.width)/2.0
y: 18
font: Font { name:"sansserif", size: 14 }
fill: Color.BLACK
content: bind title
}
var divider = Line {
startX: 0 startY: 25
endX: bind sceneWidth endY: 25
stroke: Color.rgb(138, 110, 72)
}
var shopName = "";
var shopNameText = Text {
x: 25
y: 50
font: Font { name:"sansserif", size: 13 }
fill: Color.BLACK
content: bind shopName
}
var address = "";
var addressText = Text {
x: 25
y: 68
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind address
}
var city = "";
var cityText = Text {
x: 25
y: 86
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind city
}
var phone = "";
var phoneText = Text {
x: 25
y: 104
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: bind phone
}
var comments = "";
var commentsText = Text {
x: 25
y: 130
font: Font { name:"sansserif", size: 11 }
fill: Color.BLACK
content: bind comments
wrappingWidth: bind (sceneWidth - 60)
textOrigin: TextOrigin.TOP
clip: Rectangle {
x: 23 y: 130
width: bind sceneWidth
height: bind (zipSearchPanel.translateY - 137)
}
};
var shopDetailsX: Number = 0;
var shopDetailsDisplay = Group {
content: bind [
shopNameText, addressText, cityText, phoneText, commentsText, star
]
translateX: bind shopDetailsX
}
var shopDetailsGroup = Group {
content: [ shopDetailsDisplay ]
clip: Rectangle {
x: 15
y: 32
width: bind (sceneWidth - 30)
height: bind (sceneHeight - 64)
}
}
var zipCodeLabel = Text {
font: Font { name:"sansserif", size: 12 }
fill: Color.BLACK
content: "zip code:"
textOrigin: TextOrigin.TOP
layoutInfo: LayoutInfo { vpos: javafx.geometry.VPos.CENTER }
}
var zipCodeText: TextBox = TextBox {
blocksMouse: true
columns: 7
selectOnFocus: false
text: "95054"
action: function() {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
}
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_UP) {
bgImage.requestFocus();
} else if(e.code == KeyCode.VK_RIGHT) {
if("{__PROFILE__}" == "mobile") {
searchButton.requestFocus();
}
}
}
}
var searchButton = ImageButton {
y: 2
normalImage: Image { url: "{__DIR__}images/search_normal.png" };
overImage: Image { url: "{__DIR__}images/search_over.png" };
focusImage: Image { url: "{__DIR__}images/search_focus.png" };
onMouseClicked: function(e) {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
}
onKeyPressed:function(e:KeyEvent) {
if(e.code == KeyCode.VK_ENTER) {
zipCodeText.commit();
searchCoffeeShops(zipCodeText.text.trim());
} else if(e.code == KeyCode.VK_UP) {
bgImage.requestFocus();
} else if(e.code == KeyCode.VK_LEFT) {
zipCodeText.requestFocus();
}
}
}
var zipSearchPanel : HBox = HBox {
translateX: bind (sceneWidth - zipSearchPanel.boundsInLocal.width)/2.0
translateY: bind (sceneHeight - 52)
content: [zipCodeLabel, zipCodeText, searchButton]
spacing: 10
};
var serviceProviderText : Text = Text {
translateX: bind (sceneWidth - serviceProviderText.boundsInLocal.width)/2.0
y: bind (sceneHeight - 10)
font: Font { name:"sansserif", size: 11 }
fill: Color.rgb(96, 78, 51)
content: "Web Services by Yahoo!"
}
var scene : Scene = Scene {
content: Group {
content: bind [
bgImage, titleBar, titleText, divider, shopDetailsGroup, backButton, nextButton, closeButton,
zipSearchPanel, serviceProviderText
]
clip: Rectangle {
width: bind sceneWidth
height: bind sceneHeight
arcWidth: 20
arcHeight: 20
}
}
fill: Color.TRANSPARENT
}
var stage : Stage = Stage {
title: "Coffee Shop Search"
resizable: false
style: StageStyle.TRANSPARENT
scene: bind scene
width: 240
height: 320
}
public function alert(alertTitle:String, msg:String): Void {
println(msg);
phone = alertTitle;
comments = trimString(msg, 240);
}
function run() {
searchCoffeeShops("95054");
}