/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2008, 2010 Oracle and/or its affiliates. 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 Oracle Corporation 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 screenshotmaker;
import java.lang.Math;
import java.lang.System;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.ext.swing.SwingButton;
import javafx.ext.swing.SwingLabel;
import javafx.ext.swing.SwingTextField;
import javafx.geometry.Rectangle2D;
import javafx.lang.FX;
import javafx.scene.control.TextBox;
import javafx.scene.Cursor;
import javafx.scene.CustomNode;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.Node;
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.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import screenshotmaker.ScreenCapturer;
import screenshotmaker.Util;
// FLICKR credentials,
// You can provide your own credentials there
var SECRET:String = "<Your Shared Secret>";
var API_KEY:String = "<Your API Key>";
var AUTH_TOKEN:String = "<Your Authentication Token>";
def FLICKR_EMPTY_TAGS:String = "<Your Tags>";
//Screen dimensions
def screenW:Integer =
ScreenCapturer.getScreenDimension().width;
def screenH:Integer =
ScreenCapturer.getScreenDimension().height;
// Captured screen displayed in a window 85% of the original size
def screenShotW:Number = screenW * 0.85;
def screenShotH:Number = screenH * 0.85;
def maxHiddenX:Number = screenW - screenShotW;
def maxHiddenY:Number = screenH - screenShotH;
def defaultRect:Rectangle2D = Rectangle2D{
width:screenShotW height:screenShotH }
// Right menu constants
def wp:Integer = 130;
// Some variable used to bridge the Palette events and the Stage
var movedX:Number;
var movedY:Number;
var translatedRect:Rectangle2D = defaultRect;
var imgView:ImageView;
var dragPossible:Boolean = true;
var arrow:Boolean;
var text:Boolean;
var select:Boolean;
var drag:Boolean;
// The Palette that contains the image tools
def buttonEffect:Effect = DropShadow{
offsetX: 0
offsetY: 0
color: Color.WHITE
radius: 30
};
def palette:Palette = Palette{
cache: true
translateX: screenShotW + 3
translateY: 2
transforms: Scale{
x: 0.38
y: 0.38
}
};
// Tooltips are displayed after a delay.
var timeline:Timeline;
function delayToolTip(currentToolTip:Palette.Tooltip):Void{
timeline = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames :
KeyFrame {
time : 1000ms
action:function() {
// The tooltip needs to be displayed on top of
// any other component.
currentToolTip.toFront();
currentToolTip.visible = true;
}
}
};
timeline.play();
}
// Palette selection events handling
def dragMouseOver:Boolean = bind palette.dragBtn.hover on replace {
// Effect is set only if the button is active and the button is selected
if(not palette.dragBtn.disable and
palette.currentButton != palette.dragBtn) {
palette.dragBtn.effect =
if (dragMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(dragMouseOver) {
delayToolTip(palette.dragToolTip);
} else {
palette.dragToolTip.visible = false;
timeline.stop();
}
};
palette.dragBtn.onMousePressed = function(e:MouseEvent) {
if(not palette.dragBtn.disable){
arrow = false;
text = false;
select = false;
drag = true;
palette.currentButton = palette.dragBtn;
}
}
def fitToScreenMouseOver:Boolean = bind palette.fitToScreenBtn.hover
on replace {
// Effect is set only if the button is active and the button is selected
if(not palette.fitToScreenBtn.disable) {
palette.fitToScreenBtn.effect =
if (fitToScreenMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(fitToScreenMouseOver) {
delayToolTip(palette.fitToolTip);
} else {
palette.fitToolTip.visible = false;
timeline.stop();
}
};
palette.fitToScreenBtn.onMousePressed = function(e:MouseEvent) {
movedX = 0;
movedY = 0;
translatedRect = null;
imgView.fitHeight = screenShotH;
imgView.fitWidth = screenShotW;
//Cant drag when the image fits to screen.
dragPossible = false;
palette.currentButton = palette.fitToScreenBtn;
}
palette.fitToScreenBtn.onMouseReleased = function(e:MouseEvent) {
if(not palette.fitToScreenBtn.disable) {
palette.fitToScreenBtn.disable = true;
palette.currentButton = null;
palette.dragBtn.disable = true;
palette.originalSizeBtn.disable = false;
}
}
def origMouseOver:Boolean = bind palette.originalSizeBtn.hover on replace {
// Effect is set only if the button is active and the button is selected
if(not palette.originalSizeBtn.disable) {
palette.originalSizeBtn.effect =
if (origMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(origMouseOver) {
delayToolTip(palette.originalToolTip);
} else {
palette.originalToolTip.visible = false;
timeline.stop();
}
};
palette.originalSizeBtn.onMousePressed = function(e:MouseEvent) {
movedX = 0;
movedY = 0;
translatedRect = defaultRect;
imgView.fitHeight = 0;
imgView.fitWidth = 0;
dragPossible = true;
palette.currentButton = palette.originalSizeBtn;
}
palette.originalSizeBtn.onMouseReleased = function(e:MouseEvent) {
if(not palette.originalSizeBtn.disable) {
palette.originalSizeBtn.disable = true;
palette.dragBtn.disable = false;
palette.fitToScreenBtn.disable = false;
palette.currentButton = null;
}
}
palette.arrowBtn.onMousePressed = function(e:MouseEvent) {
arrow = true;
text = false;
select = false;
drag = false;
palette.currentButton = palette.arrowBtn;
}
def arrowMouseOver:Boolean = bind palette.arrowBtn.hover on replace {
// Effect is set only if the selected button is not the arrow one.
if(palette.currentButton != palette.arrowBtn) {
palette.arrowBtn.effect =
if (arrowMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(arrowMouseOver) {
delayToolTip(palette.arrowToolTip);
} else {
palette.arrowToolTip.visible = false;
timeline.stop();
}
};
def textMouseOver:Boolean = bind palette.textBtn.hover on replace {
// Effect is set only if the selected button is not the text one.
if(palette.currentButton != palette.textBtn) {
palette.textBtn.effect =
if (textMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(textMouseOver) {
delayToolTip(palette.textToolTip);
} else {
palette.textToolTip.visible = false;
timeline.stop();
}
};
palette.textBtn.onMousePressed = function(e:MouseEvent) {
arrow = false;
select = false;
drag = false;
text = true;
palette.currentButton = palette.textBtn
}
def selectMouseOver:Boolean = bind palette.selectBtn.hover on replace {
// Effect is set only if the selected button is not the select region one.
if(palette.currentButton != palette.selectBtn) {
palette.selectBtn.effect =
if (selectMouseOver)
then buttonEffect else null;
}
//Tooltip is displayed with a delay only is pointer on top of the button.
if(selectMouseOver) {
delayToolTip(palette.selectToolTip);
} else {
palette.selectToolTip.visible = false;
timeline.stop();
}
};
palette.selectBtn.onMousePressed = function(e:MouseEvent) {
arrow = false;
text = false;
drag = false;
select = true;
palette.currentButton = palette.selectBtn;
}
/**
* An arrow that rotates following mouse drag direction
*/
class Arrow extends CustomNode {
public-init var x:Number;
public-init var y:Number;
var line:Line;
var l1:Line;
var l2:Line;
var group:Group;
var startDragX:Number;
var startDragY:Number;
var previousX:Number;
var previousY:Number;
function freeze() {
line.strokeDashArray = null;
var angle = Math.atan2(line.endY - line.startY,
line.endX - line.startX);
angle = (angle * 180 / Math.PI);
l1 = Line {
transforms:Rotate{
angle: angle
pivotX: line.endX
pivotY: line.endY
}
startX: line.endX
startY: line.endY
endX: line.endX - 7
endY: line.endY - 7
stroke: Color.BLACK
strokeWidth: 2.0
visible: true
}
l2 = Line {
transforms:Rotate{
angle: angle
pivotX:line.endX
pivotY:line.endY
}
startX: line.endX
startY: line.endY
endX: line.endX - 7
endY: line.endY + 7
stroke: Color.BLACK
strokeWidth: 2.0
visible: true
}
insert l1 into group.content;
insert l2 into group.content;
//Make the dragability visible
group.cursor = Cursor.MOVE;
}
function stretch(x:Number, y:Number) {
line.endX = x;
line.endY = y;
}
override function create():Node {
group = Group{
onMousePressed:function(e:MouseEvent) {
//Reset the drag state.
startDragX = e.sceneX;
startDragY = e.sceneY;
previousX = 0;
previousY = 0;
// Back to creation state.
delete l1 from group.content;
delete l2 from group.content;
line.strokeDashArray = [5,5]
}
onMouseReleased:function(e:MouseEvent) {
//When drag stop, freeze the arrow.
freeze();
}
onMouseDragged:function(e:MouseEvent) {
var constrainedX:Number;
var constrainedY:Number;
// Need to compute direction for boundaries computation
var directionX:Number = (e.sceneX - startDragX) - previousX;
var directionY:Number = (e.sceneY - startDragY) - previousY;
// X boundaries
var maxX:Number = Math.max(line.startX, line.endX);
var minX:Number = Math.min(line.startX, line.endX);
if((minX <= 0 and directionX < 0) or
((e.sceneX + (maxX - e.sceneX) >= screenShotW)
and directionX > 0)) {
constrainedX = previousX;
}else {
constrainedX = e.sceneX - startDragX;
}
// Y boundaries, 7 is the height of the head.
var maxY:Number = Math.max(line.startY, line.endY);
var minY:Number = Math.min(line.startY, line.endY);
if((minY <= 7 and directionY < 0) or
((e.sceneY + (maxY - e.sceneY) + 7 >= screenShotH)
and directionY > 0)) {
constrainedY = previousY;
}else {
constrainedY = e.sceneY - startDragY;
}
// Compute move delta
var deltaX:Number = constrainedX - previousX;
var deltaY:Number = constrainedY - previousY;
line.startX = line.startX + deltaX;
line.startY = line.startY + deltaY;
line.endX = line.endX + deltaX;
line.endY = line.endY + deltaY;
// Store current coordinates for next computation.
previousX = constrainedX;
previousY = constrainedY;
}
content: [
line = Line{
endX: x
endY: y
startX: x
startY: y
stroke: Color.BLACK
strokeDashOffset: 0
strokeWidth: 2.0
strokeDashArray: [ 5, 5 ]
}
]
}
}
}
/**
* An editable text.
* Double click on the text to go to edition. Type Return key to stop editing.
* Click and drag the text to change its location.
*/
class EditableText extends CustomNode {
public-init var x:Number;
public-init var y:Number;
var tb:TextBox;
function stopEditing():Void{
tb.unselect();
tb.editable = false;
}
override function create():Node {
var group = Group {
content: [
tb = TextBox {
style: "font-family: 'Verdana'; font-size: 20pt; border-fill:transparent; "
"background-fill:transparent; focus-fill:transparent;shadow-fill:transparent"
// Need to substract the border to make the text displayed where
// the mouse pointer is.
translateX: x - 7
translateY: y - 20
visible: true
focusTraversable:true
columns:15
// Height is set to 40 to cope with font size.
height: 40
text: "Type some text"
selectOnFocus: true
onKeyTyped: function(k:KeyEvent){
// Increase the width to avoid the text to
// be cropped. Only if width inside the borders
if(tb.translateX + tb.width < screenShotW - 5)
tb.width +=10;
}
onMousePressed:function(e:MouseEvent){
if(e.clickCount >= 2) {
tb.editable = true;
}
}
onMouseDragged:function(e:MouseEvent) {
tb.unselect();
tb.cursor = Cursor.MOVE;
// Change the style to display the borders
tb.style = "font-family: 'Verdana'; font-size: 20pt; "
"border-fill:gray; background-fill:transparent; focus-fill:transparent;shadow-fill:transparent";
// Compute constraints
var constrainedX:Number;
var constrainedY:Number;
if(e.sceneX < 0){
constrainedX = 0;
}else {
constrainedX = e.sceneX;
}
if(constrainedX + tb.width > screenShotW)
constrainedX = screenShotW - tb.width;
if(e.sceneY < 0) {
constrainedY = 0;
} else {
constrainedY = e.sceneY;
}
if(constrainedY + tb.height > screenShotH)
constrainedY = screenShotH - tb.height;
tb.translateX = constrainedX;
tb.translateY = constrainedY;
}
onMouseReleased:function(e:MouseEvent) {
// Back to default values
tb.cursor = Cursor.DEFAULT;
tb.style = "font-family: 'Verdana'; font-size: 20pt; "
"border-fill:transparent; background-fill:transparent; focus-fill:transparent;shadow-fill:transparent";
}
action:function() {
stopEditing();
}
}
]
}
// Text can"t expend outside the borders of the image.
if(tb.translateX + tb.width > screenShotW - 5)
tb.width = screenShotW - x;
tb.requestFocus();
return group;
}
}
/**
* A Image region selector. Composed of a Label and a Rectangle.
* The image region covered by the rectangle is what is exported to Flickr or
* saved to disk.
*/
class SelectRegionRectangle extends CustomNode {
public-init var originX:Number;
public-init var originY:Number;
public var width:Number = bind selectRectangle.width;
public var height:Number = bind selectRectangle.height;
var labelValue:String;
var labelRectangle:Rectangle;
var selectRectangle:Rectangle;
override var visible = false;
function freeze() {
labelValue="";
labelRectangle.visible = false;
}
function enlarge(x:Number, y:Number) {
selectRectangle.width= x - originX;
selectRectangle.height = y - originY;
labelValue = "width={
java.lang.Integer.valueOf(selectRectangle.width)}height={
java.lang.Integer.valueOf(selectRectangle.height)}";
}
function reset() {
enlarge(0,0);
visible = true;
labelRectangle.visible = true;
}
override function create():Node {
var group = Group {
content: [
labelRectangle = Rectangle {
x: bind originX
y: bind originY - 22
width: 185
height:20
opacity: 0.4
visible: true
fill: Color.CHARTREUSE
},
Text {
content: bind labelValue
x: bind originX
y: bind originY - 5
visible: true
font:Font {
name: "Verdana"
size: 15
}
},
selectRectangle = Rectangle {
x: bind originX
y: bind originY
opacity: 0.4
visible: bind visible
fill: Color.CHARTREUSE
}
]
}
}
}
// Small frame displayed on the bottom of the screen
// Screenshot capture is operated from this widget
def widget: Stage = Stage {
x: screenW - 150
y: screenH - 100
resizable: false
visible: true
scene:Scene {
content: {
SwingButton {
text: "Capture screen"
action:function():Void {
widget.visible = false;
FX.deferAction(function() { captureAndRetouch(); } );
}
}
}
}
onClose: function() {
System.exit(0);
}
}
/**
* The palette being reused each time a screenshot is captured,
* we reset the state.
*/
function resetPalette() {
movedX = 0;
movedY = 0;
translatedRect = defaultRect;
dragPossible = true;
arrow = false;
text = false;
select= false;
drag = false;
palette.reset();
}
function captureAndRetouch():Void{
var screenFile = ScreenCapturer.capture();
var imgURL = screenFile.toURL().toString();
//reset the palette
resetPalette();
// Picture retouch frame
var f:Stage = Stage {
title: "Screenshot Maker";
visible: true
resizable: false
var originX:Number;
var originY:Number;
var disabledRectangleVisibility:Boolean = false;
var selectRectangle:SelectRegionRectangle;
var groupRef:Group;
var currentArrow:Arrow;
var status:String = " ";
var currentCursor:Cursor = Cursor.DEFAULT;
var disabled:Boolean = false;
var previousX:Number;
var previousY:Number;
var selectionRectangle = function() :
java.awt.Rectangle {
// To retrieve the absolute screen coordinates of the selection,
// we need to get the Stage coordinates (that are
// absolute to the screen, add the Scene ones (to remove the window
// decoration) and add the Selection Rectangle ones if visible.
var x:Number = f.x + f.scene.x;
var y:Number = f.y + f.scene.y;
var w:Number;
var h:Number;
if(selectRectangle.visible) {
x += selectRectangle.originX;
y += selectRectangle.originY;
w = selectRectangle.width;
h = selectRectangle.height;
selectRectangle.visible = false;
} else {
w = screenShotW;
h = screenShotH;
}
return
new java.awt.Rectangle(x, y, w, h);
}
var disable = function():Void {
disabledRectangleVisibility=true;
currentCursor = Cursor.WAIT;
disabled = true;
}
var enable = function():Void {
disabledRectangleVisibility = false;
currentCursor = Cursor.DEFAULT;
disabled = false;
}
var computeTranslation = function(maxHidden:Number,
current:Number, increment:Number):Number {
var coordinate:Number;
if(Math.abs(current) >= maxHidden)
{
if(increment > 0) {
coordinate = current + increment;
} else {
coordinate = current;
}
}else {
if(current + increment > 0) {
coordinate = 0;
} else {
coordinate = current + increment;
}
}
return coordinate;
}
onClose:function() {
displayStage(widget);
}
scene:
Scene {
content: [
groupRef = Group {
cursor: bind currentCursor;
content: [
Rectangle {
width: screenShotW + wp + 3
height: screenShotH + 3
fill: Color.BLACK
},
Rectangle {
width: screenShotW
height: screenShotH
fill: null
stroke: Color.WHITE
},
imgView = ImageView{
viewport: bind translatedRect
transforms: Translate {
x: bind movedX
y: bind movedY
}
image:Image { url: imgURL }
onMouseDragged:function(e:MouseEvent) {
if(disabled)
return;
var constrainedX:Number;
var constrainedY:Number;
// Frame boundaries computation
constrainedX = e.sceneX;
if(constrainedX > screenShotW)
constrainedX = screenShotW;
constrainedY = e.sceneY;
if(constrainedY > screenShotH)
constrainedY = screenShotH;
if(arrow){
currentArrow.stretch(constrainedX,
constrainedY);
return;
}
if(select){
selectRectangle.enlarge(constrainedX,
constrainedY);
return;
}
if(drag){
if(dragPossible){
// Outside the imgView, the mouse sceneX
// and sceneY positions are invalid
// No image dragging in these contexts.
if(constrainedX == screenShotW or
constrainedY == screenShotH or
constrainedX < 0 or
constrainedY < 0) {
previousX = constrainedX;
previousY = constrainedY;
return;
}
var incrementX = constrainedX-previousX;
var incrementY = constrainedY-previousY;
previousX = constrainedX;
previousY = constrainedY;
movedX = computeTranslation(maxHiddenX,
movedX, incrementX);
movedY = computeTranslation(maxHiddenY,
movedY, incrementY);
translatedRect = Rectangle2D {
width: screenShotW - movedX
height: screenShotH - movedY
}
}
return;
}
}
onMouseReleased:function (e:MouseEvent){
if(disabled)
return;
imgView.cursor = Cursor.DEFAULT;
arrow = false;
text = false;
select = false;
drag = false;
palette.currentButton = null;
if(currentArrow != null) {
currentArrow.freeze();
currentArrow = null;
}
selectRectangle.freeze();
}
onMousePressed:function (e:MouseEvent){
if(disabled)
return;
// We stop editing all texts.
for(node in groupRef.content) {
if(node instanceof EditableText)
(node as EditableText).stopEditing();
}
if(palette.currentButton == null)
return;
originX = e.sceneX;
originY = e.sceneY;
selectRectangle.visible = false;
if(arrow){
currentArrow = Arrow {
x: e.sceneX
y: e.sceneY
}
insert currentArrow into groupRef.content;
return;
}
if(text){
var currentText = EditableText {
x: originX
y: originY
}
insert currentText into groupRef.content;
return;
}
if(select){
selectRectangle.reset();
return;
}
if(drag){
previousX = originX;
previousY = originY;
imgView.cursor = Cursor.MOVE;
return;
}
}
},
selectRectangle = SelectRegionRectangle {
originX: bind originX
originY: bind originY
},
Rectangle {
x: 0
y: 0
width: screenShotW
height: screenShotH
opacity: 0.5
visible: bind disabledRectangleVisibility
fill: Color.BLACK
},
palette,
VBox {
translateX: screenShotW
translateY: 170
width: wp
height: screenShotH
content: [
SwingButton {
text: "Save To Disk"
width: wp
action:function():Void {
saveFileToDisk();
}
},
SwingButton {
text: "Flickr Upload"
width: wp
action:function():Void {
status = "";
var screenRect:java.awt.Rectangle =
selectionRectangle();
FX.deferAction(function() {
var file = ScreenCapturer.
capture(screenRect);
disable();
var flickrFrame:Stage = Stage {
var wf:Number = 400;
var hf:Number = 250;
title: "Upload"
resizable: false
width: wf
height: hf
visible: true
var tags:SwingTextField;
var api_key:SwingTextField;
var api_secret:SwingTextField;
var auth_token:SwingTextField;
onClose:function() {
enable();
}
scene:Scene {
content:Group {
content: [
Rectangle {
width: wf
height: hf
fill: Color.BLACK
},
VBox {
translateX: 5
width: wf
height:hf
content: [
SwingLabel {
text: "Flickr Tags: (Optional)"
foreground: Color.WHITE},
tags = SwingTextField {
text: FLICKR_EMPTY_TAGS
width: wf - 15
} ,
SwingLabel {
text: "Flickr Api Key:"
foreground: Color.WHITE},
api_key = SwingTextField {
text: API_KEY
width: wf - 15
},
SwingLabel {
text: "Flickr Shared Secret:"
foreground: Color.WHITE},
api_secret =
SwingTextField {
text: SECRET
width:wf - 15
},
SwingLabel {
text:"Flickr Authentication Token:"
foreground:
Color.WHITE},
auth_token =
SwingTextField {
text: AUTH_TOKEN
width:wf - 15 }
,
SwingButton {
text: "Upload"
translateX: 20
translateY: 10
action :
function():Void {
flickrFrame.visible =
false;
FX.deferAction(function() {
if(api_key.text.length() == 0
or api_secret.text.length() == 0
or auth_token.text.length() == 0)
{
status =
"Invalid keys";
return
}
API_KEY = api_key.text;
SECRET = api_secret.text;
AUTH_TOKEN = auth_token.text;
if(FLICKR_EMPTY_TAGS.equals(tags.text))
tags.text = null;
var req = FlickrPhotoUpload {
api_key: api_key.text
secret: api_secret.text
auth_token: auth_token.text
tags: tags.text
file: file
type: "jpg"
override var done on replace{
if(done) {
enable();
if(not success){
status = "Upload failed";
} else {
displayStage(widget);
closeStage(f);
}
}
}
}
req.start();
return;
});
}
},
SwingButton {
text: "Cancel"
translateX: 95
translateY: -18
action :
function( ):Void {
flickrFrame.
close();
}
}
]
}
]
}
}
}
return;
});
}
},
SwingButton {
text:"Back to Capture"
width:wp
action:function() : Void {
closeStage(f);
}
},
SwingLabel {text:bind status width:120
foreground:Color.RED}
]}
]}
]}
var saveFileToDisk = function ():Void {
status = "";
var screenRect:java.awt.Rectangle =
selectionRectangle();
FX.deferAction(function() {
var file:java.io.File =
ScreenCapturer.
capture(screenRect);
var fc =
javax.swing.JFileChooser{};
var target =
new java.io.File(
fc.getCurrentDirectory(),
"screenshot.jpg");
fc.setSelectedFile(target);
var ff = Util.JPGFileFilter{};
fc.setFileFilter(ff);
disable();
if (fc.showSaveDialog(null) ==
javax.swing.JFileChooser.APPROVE_OPTION) {
try {
var imgFile:java.io.File =
fc.getSelectedFile();
var cancel:SwingButton;
if(imgFile.exists()) {
var confirmFrame :
Stage = Stage {
var yesClicked:Boolean;
var wf:Number = 290;
var hf:Number = 100;
title: "Warning"
resizable:false
width:wf
height:hf
visible: true
onClose:function() {
if(yesClicked) {
imgFile.createNewFile();
Util.copyFile(file,
imgFile);
displayStage(widget);
closeStage(f);
} else {
enable();
}
}
scene: Scene {
content: Group {
content: [
Rectangle {
width: 290
height: 100
fill: Color.BLACK
},
VBox {
translateX: 10
width: wf
height:hf
content: [
SwingLabel {
text:
"The file already exists, do you want to replace it?"
foreground:
Color.WHITE
},
SwingButton {
text: "Replace"
translateX: 55
translateY: 10
action:
function( ): Void {
yesClicked = true;
confirmFrame.close();
}
},
cancel = SwingButton {
text: "Cancel"
translateX: 150
translateY: -18
action: function( ):Void {
yesClicked = false;
confirmFrame.close();
}
}
]
}
]
}
}
}
cancel.requestFocus();
} else {
imgFile.createNewFile();
Util.copyFile(file,
imgFile);
displayStage(widget);
closeStage(f);
}
}catch(e:java.lang.Exception){
e.printStackTrace();
FX.print("Exception {e}");
status = e.getMessage();
}
} else {
enable();
}
});
}
}
displayStage(f);
}
function displayStage(f:Stage):Void{
// Simple effect to make the stage to be opened smoothly
def temp = f;
def temp1 = f.scene.content[0];
def displayStage = Timeline {
keyFrames: [
at (0s) {temp.visible => true},
at (0s) {temp1.opacity => 0.0},
at (1s) {temp1.opacity => 1.0}
]
}
displayStage.play();
}
function closeStage(f:Stage):Void{
// Simple effect to make the stage to be closed smoothly
def temp = f.scene.content[0];
def closeStage = Timeline {
keyFrames: [
at (0s) {temp.opacity => 1.0},
at (0.5s) {temp.opacity => 0.0},
KeyFrame {
time : 0.5s
action: function() {
f.close();
}
}
]
}
closeStage.play();
}