/*
* 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 podcastfeedviewer;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.media.Media;
import podcastfeedviewer.PodcastParser;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Color;
import javafx.scene.paint.Stop;
import javafx.util.Sequences;
import podcastfeedviewer.LocationControll;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.stage.StageStyle;
import javafx.scene.effect.Glow;
import javafx.date.DateTime;
import podcastfeedviewer.media.MediaBox;
public def desktop = "{__PROFILE__}".equals("desktop");
public def mobile = "{__PROFILE__}".equals("mobile");
public def browser = "{__PROFILE__}".equals("browser");
def mobileXRatio = 0.375 ;
def mobileYRatio = 0.6667 ;
def mobileXLandScapeRatio = 0.5;
def mobileYLandScapeRatio = 0.5;
def appletRatioX = 0.9375;
def appletRatioY = 0.9375;
public var widthRatio1 = if (mobile) 0.375 else if (browser) 0.9375 else 1;
public var heightRatio1 =if (mobile) 0.6667 else if (browser) 0.9375 else 1;
public var defaultWidth = bind (640 * widthRatio1);
public var defaultHeight = bind (480 * heightRatio1);
public var feedInterval = 20m;
public def iconSize = bind (50.0 *widthRatio1);
public def gap = bind (20.0 * widthRatio1);
public def buttonGap = bind (5 * widthRatio1);
public def toolbarHieght = bind (55 * heightRatio1);
public def textBoxSize = bind (250 * widthRatio1);
public def mediaButtonGap = bind (5 * widthRatio1);
public def applicationTitle = "PodcastViewer";
var displayFeedTitle:String = "Podcast Viewer";
public var currentPodcastFeed:PodcastFeed on replace {
if ( currentPodcastFeed != null ){
displayFeedTitle = currentPodcastFeed.title;
currentPodcastMedia = currentPodcastFeed.medias[0];
}
}
public var locations:String[];
public var locationControll = LocationControll{
width:bind defaultWidth
height: bind (toolbarHieght - 5 *heightRatio1)
};
public var location:String on replace oldLocation{
Main.log("Location changed {location} - oldLocation {oldLocation}");
mediaBox.loading = true;
currentPodcastFeed = PodcastParser.getPodcastFeed(location);
if ( currentPodcastFeed == null and location != null and location != ""){
var parser = PodcastParser{
location:location
}
}
}
public var currentPodcastMedia:PodcastMedia on replace {
if ( currentPodcastMedia != null ){
mediaBox.loading = false;
}
}
public-read var mediaBox:MediaBox = MediaBox {
visible: true
mediaPlayerAutoPlay: true
mediaViewHeight: bind (defaultHeight - locationControll.height - iconSize - gap)
mediaViewWidth: bind defaultWidth
translateY: bind locationControll.height + 5 * heightRatio1
mediaSourceURL:bind currentPodcastMedia.mediaURL
mediaTitle: bind currentPodcastMedia.title
}
var previousMedia:ImageView = ImageView{
fitHeight: bind iconSize
fitWidth: bind iconSize
translateY: bind (defaultHeight - iconSize - gap) + 5 * heightRatio1;
translateX: bind mediaButtonGap
image: Image{ url:"{__DIR__}resources/arrow_left.png"}
onMouseEntered: function(e:MouseEvent){
previousMedia.effect = Glow {}
}
onMouseExited: function(e:MouseEvent){
previousMedia.effect = null;
}
onMousePressed:function(e:MouseEvent){
if ( currentPodcastFeed == null ){
return;
}
var index = Sequences.indexOf(currentPodcastFeed.medias,currentPodcastMedia);
if ( index == 0){
index = sizeof currentPodcastFeed.medias - 1;
}else index --;
log("Clicked previous -> index = {index}\n size -> {sizeof currentPodcastFeed.medias}");
if ( currentPodcastMedia .mediaURL != currentPodcastFeed.medias[index].mediaURL)
currentPodcastMedia = currentPodcastFeed.medias[index];
}
}
var nextMedia:ImageView = ImageView{
translateY: bind (defaultHeight - iconSize - gap) + 5 * heightRatio1;
translateX: bind ( defaultWidth - (iconSize+5 * heightRatio1));
fitHeight: bind iconSize
fitWidth: bind iconSize
image: Image{ url:"{__DIR__}resources/arrow_right.png"}
onMouseEntered: function(e:MouseEvent){
nextMedia.effect = Glow {}
}
onMouseExited: function(e:MouseEvent){
nextMedia.effect = null
}
onMousePressed:function(e:MouseEvent){
if ( currentPodcastFeed == null ){
return;
}
var index = Sequences.indexOf(currentPodcastFeed.medias,currentPodcastMedia);
log("Clicked next -> index = {index}\n size -> {sizeof currentPodcastFeed.medias}");
if ( index >= (sizeof currentPodcastFeed.medias - 1)){
index = 0;
}else index ++;
currentPodcastMedia = currentPodcastFeed.medias[index];
}
}
var mediaDescription:Text = Text {
translateX: bind (iconSize + 2 * buttonGap)
translateY: bind (defaultHeight - iconSize)
font : Font {
size: (12 * widthRatio1)as Integer
}
wrappingWidth: bind (defaultWidth - (2*iconSize) - 2* buttonGap)* 0.95
content: bind if( currentPodcastMedia != null)
"{currentPodcastMedia.title} - {currentPodcastMedia.data}" else "";
}
var titleBar:Rectangle = Rectangle {
width: bind defaultWidth
height: bind 5 * heightRatio1
fill: Color.TRANSPARENT
visible: bind ("{__PROFILE__}" != "browser")
onMouseDragged: function(e) {
stage.x = stage.x + e.dragX;
stage.y = stage.y + e.dragY;
}
}
var closeButton:ImageView = ImageView{
translateX: bind (defaultWidth - iconSize * 0.25 )
translateY: 0.0
image: Image{url: "{__DIR__}resources/close.png"}
visible : bind ("{__PROFILE__}" != "browser")
fitHeight: bind iconSize * 0.25
fitWidth: bind iconSize * 0.25
opacity:1.0
onMouseEntered: function(e:MouseEvent){
closeButton.effect = Glow{}
}
onMouseExited: function(e:MouseEvent){
closeButton.effect = null;
}
onMousePressed: function(e) {
javafx.lang.FX.exit();
}
}
public var VERBOSE = true;
public function log(e){
if (VERBOSE)
println(e);
}
var scene = Scene {
content: Group {
content:[mediaBox,
locationControll,previousMedia,nextMedia,mediaDescription,closeButton]
}
}
var firstLoad = true;
var height = bind scene.height on replace {
if (not firstLoad and mobile){
widthRatio1 = mobileXLandScapeRatio;
heightRatio1 = mobileYLandScapeRatio;
}
firstLoad = false;
}
var stage:Stage = Stage {
resizable:false
title: bind displayFeedTitle
width: bind defaultWidth
height:bind defaultHeight
scene: scene
style: StageStyle.TRANSPARENT
}
public function run(){
stage;
PersistenceHandler.load();
}