add a timer and carry forward its value to the next activity - android-activity

how to add a timer to an activity and carry forward its values to the next activity?
I have a timer in my ShuffleButtons.class but when i move on to the next activity ShuffleButtons1.class, the timer value starts from zero. Can somebody tell me how to pass on the timer value to the next activity?
Below is my code :
import java.util.ArrayList;
import java.util.Collections;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class ShuffleButtons extends Activity {
int id = 1;
static Toast button_press;
int a = 0;
private TextView timerValue;
private long startTime = 0L;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
#SuppressLint("ShowToast")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.shuffle );
timerValue = (TextView) findViewById(R.id.timerValue);
button_press= Toast.makeText(this, "1 Presssed", Toast.LENGTH_SHORT);
//create another two linear layouts which will host 5 buttons horizontally
LinearLayout top_compte = (LinearLayout)findViewById(R.id.top_compte);
LinearLayout bottom_calculator = (LinearLayout)findViewById(R.id.bottom_calculator);
// Create an ArrayList to hold the Button objects that we will create
ArrayList<Button> buttonList = new ArrayList<Button>();
// Create the Buttons, set their text as numeral value of the index variable
for (int i = 0; i < 4; i++) {
final Button b = new Button(this);
b.setText("" + (i+1));
b.setGravity(Gravity.CENTER_HORIZONTAL);
b.setId(i+1); // Set an id to Button
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dealWithButtonClick(b);
}
public void dealWithButtonClick(Button b) {
switch(b.getId()) {
case 1:
if (a==0) {
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
a=1;
}
button_press.setText("1 Pressed");
button_press.show();
break;
case 2:
if (a==1) {
a=2;
button_press.setText("2 Pressed");
button_press.show();
}else {
button_press.setText("You Pressed the wrong button");
button_press.show();
}
break;
case 3:
if (a==2) {
a=3;
button_press.setText("3 Pressed");
button_press.show();
}else {
button_press.setText("You Pressed the wrong button");
button_press.show();
}
break;
case 4:
if (a==3) {
timeSwapBuff += timeInMilliseconds;
customHandler.removeCallbacks(updateTimerThread);
a=4;
button_press.setText("Good Going");
button_press.show();
// here i move on from ShuffleButtons.class to ShuffleButtons1.class
Intent intent = new Intent(getApplicationContext(),ShuffleButtons1.class);
startActivity(intent);
finish();
}else {
button_press.setText("You Pressed the wrong button");
button_press.show();
}
break;
}
}
});
buttonList.add(b);
}
// Shuffle
Collections.shuffle(buttonList);
for (int i = 0; i < 4; i++) {
// Add the first five Buttons to top_compte
// Add the last five Buttons to bottom_calculator
if (i < 2) {
top_compte.addView(buttonList.get(i));
} else {
bottom_calculator.addView(buttonList.get(i));
}
}
}
// Generates and returns a valid id that's not in use
public int generateUniqueId(){
View v = findViewById(id);
while (v != null){
v = findViewById(++id);
}
return id++;
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (updatedTime / 1000);
int mins = secs / 60;
secs = secs % 60;
int milliseconds = (int) (updatedTime % 1000);
timerValue.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));
customHandler.postDelayed(this, 0);
}
};
}

Don't pass your Timer.
Start your timer in a separate Service, which means to let it run in background.
Make the timer globally accessible using Singleton pattern or custom Application class.
And then access it whenever and wherever you need it.
That's the cleverer way to do it. See this if you are not familiar with the Android Service component.

Related

Place unknown amount of nodes in GridPane

I am making a maze from a text file. The text file contains two integers on separate lines. These decide a number of rows and columns. Then the text file forms a maze by the use of '#' for walls, ' ' for passage, '*' for the players start position and '-' for the exit. When I start the program, I am able to select the file but the nodes won't align up nicely in rows and columns. Seems like they all ends up in a pile in the same place. Any tips?
package application;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javafx.application.Application;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
public class Main extends Application {
LabyrintRute[][] Labyrint;
int X;
int Y;
int startx;
int starty;
Spiller spilleren;
#Override
public void start(Stage primaryStage) {
try {
GridPane root = new GridPane();
Scene scene = new Scene(root, X*100, Y*100, Color.BLACK);
Spiller spilleren = new Spiller(startx, starty);
filLeser();
root.add(spilleren.getUtseende(), spilleren.getxPossisjon(), spilleren.getyPossisjon());
for(int x = 1; x<X; x++){
for(int y = 1; y<Y; y++){
root.add(Labyrint[x][y].getUtseende(), Labyrint[x][y].getxKoordinat(), Labyrint[x][y].getyKoordinat());
}
}
scene.setOnKeyPressed(new FilLytter(this));
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("Labyrintspill");
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public void filLeser() {
String teksten = "";
File fila;
FileChooser filvelger = new FileChooser();
filvelger.setTitle("Åpne en tekstfil");
filvelger.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
fila = filvelger.showOpenDialog(null);
try (Scanner filleser = new Scanner(fila)) {
X = filleser.nextInt();
Y = filleser.nextInt();
teksten = filleser.nextLine();
Labyrint = new LabyrintRute [X][Y];
while (filleser.hasNext()) {
teksten = filleser.nextLine();
for (int i = 1;i< X;i++) {
for (int rad = 1; rad < Y; rad++){
char tegn = teksten.charAt(i);
switch (tegn) {
case '#':
Labyrint[i][rad] = new Vegg(i, rad);
break;
case ' ':
Labyrint[i][rad] = new Gang(i, rad);
break;
case '-':
Labyrint[i][rad] = new Utgang(i, rad);
break;
case '*':
Labyrint[i][rad] = new Gang(i, rad);
startx = i;
starty = rad;
break;
}
}
}
}
} catch (FileNotFoundException e) {
System.out.println("Kan ikke åpne fila!");
e.printStackTrace();
}
}
public void flyttSpiller(int deltax, int deltay) {
int nyx = spilleren.getxPossisjon() + deltax;
int nyy = spilleren.getyPossisjon() + deltay;
Labyrint[nyx][nyy].flyttHit(spilleren);
}
public static void main(String[] args) {
launch(args);
}
}
The is the "Vegg"(wall), "Gang"(passage) and "Utgang"(exit) methods are all extensions of the "Labyrintrute" method:
package application;
import javafx.scene.Node;
public abstract class LabyrintRute {
private int xKoordinat;
private int yKoordinat;
public LabyrintRute(int xKoordinat, int yKoordinat) {
this.xKoordinat = xKoordinat;
this.yKoordinat = yKoordinat;
}
public int getxKoordinat() {
return xKoordinat;
}
public int getyKoordinat() {
return yKoordinat;
}
public abstract void flyttHit(Spiller spilleren);
public abstract Node getUtseende();
}
The "vegg"(wall), "gang"(passage) and "utgang"(exit) methods are all pretty similiar. So I'm just posting one of them:
package application;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
public class Utgang extends LabyrintRute {
private Node utseende;
public Utgang(int xKoordinat, int yKoordinat) {
super(xKoordinat, yKoordinat);
utseende = new Rectangle(10, 10, Color.BLACK);
}
#Override
public void flyttHit(Spiller spilleren) {
spilleren.setxPossisjon(getxKoordinat());
spilleren.setyPossisjon(getyKoordinat());
JFrame ramme = new JFrame();
JOptionPane.showMessageDialog(ramme, "Gratulerer! Du fant veien ut :D");
System.exit(0);
}
#Override
public Node getUtseende() {
return utseende;
}
}

Selecting a period or a date using ONE JavaFX 8 DatePicker

On the application I am currently working, it is necessary to select a single date or a period from the same JavaFX 8 DatePicker.
The preferred way of doing this would be as follows:
Selecting a single date - same as default behaviour of the DatePicker.
Selecting a period - select start/end date by holding down the mouse button and drag to the desired end/start date. When the mouse button is released you have defined your period. The fact that you cannot select dates other than those displayed is acceptable.
Editing should work for both single date (ex 24.12.2014) and period ( ex: 24.12.2014 - 27.12.2014)
A possible rendering of the selected period (minus the content of the text editor) above would look like this:
Where orange indicates current date, blue indicates selected period. The picture is from a prototype I made, but where the period is selected by using 2 DatePickers rather than one.
I had a look at the sourcecode for
com.sun.javafx.scene.control.skin.DatePickerContent
which has a
protected List<DateCell> dayCells = new ArrayList<DateCell>();
in order to find a way of detecting when the mouse selected a date end when the mouse was released (or maybe detecting a drag).
However I am not quite sure how to go about it. Any suggestions?
I am attaching the simple prototype code I have made so far (that makes use of 2 rather than the desired 1 datepicker).
import java.time.LocalDate;
import javafx.beans.property.SimpleObjectProperty;
public interface PeriodController {
/**
* #return Today.
*/
LocalDate currentDate();
/**
* #return Selected from date.
*/
SimpleObjectProperty<LocalDate> fromDateProperty();
/**
* #return Selected to date.
*/
SimpleObjectProperty<LocalDate> toDateProperty();
}
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javafx.util.StringConverter;
public class DateConverter extends StringConverter<LocalDate> {
private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); // TODO i18n
#Override
public String toString(LocalDate date) {
if (date != null) {
return dateFormatter.format(date);
} else {
return "";
}
}
#Override
public LocalDate fromString(String string) {
if (string != null && !string.isEmpty()) {
return LocalDate.parse(string, dateFormatter);
} else {
return null;
}
}
}
import static java.lang.System.out;
import java.time.LocalDate;
import java.util.Locale;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class PeriodMain extends Application {
private Stage stage;
public static void main(String[] args) {
Locale.setDefault(new Locale("no", "NO"));
launch(args);
}
#Override
public void start(Stage stage) {
this.stage = stage;
stage.setTitle("Period prototype ");
initUI();
stage.getScene().getStylesheets().add(getClass().getResource("/period-picker.css").toExternalForm());
stage.show();
}
private void initUI() {
VBox vbox = new VBox(20);
vbox.setStyle("-fx-padding: 10;");
Scene scene = new Scene(vbox, 400, 200);
stage.setScene(scene);
final PeriodPickerPrototype periodPickerPrototype = new PeriodPickerPrototype(new PeriodController() {
SimpleObjectProperty<LocalDate> fromDate = new SimpleObjectProperty<>();
SimpleObjectProperty<LocalDate> toDate = new SimpleObjectProperty<>();
{
final ChangeListener<LocalDate> dateListener = (observable, oldValue, newValue) -> {
if (fromDate.getValue() != null && toDate.getValue() != null) {
out.println("Selected period " + fromDate.getValue() + " - " + toDate.getValue());
}
};
fromDate.addListener(dateListener);
toDate.addListener(dateListener);
}
#Override public LocalDate currentDate() {
return LocalDate.now();
}
#Override public SimpleObjectProperty<LocalDate> fromDateProperty() {
return fromDate;
}
#Override public SimpleObjectProperty<LocalDate> toDateProperty() {
return toDate;
}
});
GridPane gridPane = new GridPane();
gridPane.setHgap(10);
gridPane.setVgap(10);
Label checkInlabel = new Label("Check-In Date:");
GridPane.setHalignment(checkInlabel, HPos.LEFT);
gridPane.add(periodPickerPrototype, 0, 1);
vbox.getChildren().add(gridPane);
}
}
import java.time.LocalDate;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.DateCell;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import javafx.util.Callback;
import javafx.util.StringConverter;
/**
* Selecting a single date or a period - only a prototype.
* As long as you have made an active choice on the {#code toDate}, the {#code fromDate} and {#code toDate} will have the same date.
*/
public class PeriodPickerPrototype extends GridPane {
private static final String CSS_CALENDAR_BEFORE = "calendar-before";
private static final String CSS_CALENDAR_BETWEEN = "calendar-between";
private static final String CSS_CALENDAR_TODAY = "calendar-today";
private static final boolean DISPLAY_WEEK_NUMBER = true;
private Label fromLabel;
private Label toLabel;
private DatePicker fromDate;
private DatePicker toDate;
private StringConverter<LocalDate> converter;
private PeriodController controller;
private ChangeListener<LocalDate> fromDateListener;
private ChangeListener<LocalDate> toDateListener;
private Callback<DatePicker, DateCell> toDateCellFactory;
private Callback<DatePicker, DateCell> fromDateCellFactory;
private Tooltip todayTooltip;
private boolean toDateIsActivlyChosenbyUser;
public PeriodPickerPrototype(final PeriodController periodController)
{
this.controller = periodController;
createComponents();
makeLayout();
createHandlers();
bindAndRegisterHandlers();
i18n();
initComponent();
}
public void createComponents() {
fromLabel = new Label();
toLabel = new Label();
fromDate = new DatePicker();
toDate = new DatePicker();
todayTooltip = new Tooltip();
}
public void createHandlers() {
fromDate.setOnAction(event -> {
if ((!toDateIsActivlyChosenbyUser) || fromDate.getValue().isAfter(toDate.getValue())) {
setDateWithoutFiringEvent(fromDate.getValue(), toDate);
toDateIsActivlyChosenbyUser = false;
}
});
toDate.setOnAction(event -> toDateIsActivlyChosenbyUser = true);
fromDateCellFactory = new Callback<DatePicker, DateCell>() {
#Override public DateCell call(final DatePicker datePicker) {
return new DateCell() {
#Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
getStyleClass().removeAll(CSS_CALENDAR_TODAY, CSS_CALENDAR_BEFORE, CSS_CALENDAR_BETWEEN);
if ((item.isBefore(toDate.getValue()) || item.isEqual(toDate.getValue())) && item.isAfter(fromDate.getValue())) {
getStyleClass().add(CSS_CALENDAR_BETWEEN);
}
if (item.isEqual(controller.currentDate())) {
getStyleClass().add(CSS_CALENDAR_TODAY);
setTooltip(todayTooltip);
} else {
setTooltip(null);
}
}
};
}
};
toDateCellFactory =
new Callback<DatePicker, DateCell>() {
#Override
public DateCell call(final DatePicker datePicker) {
return new DateCell() {
#Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
setDisable(item.isBefore(fromDate.getValue()));
getStyleClass().removeAll(CSS_CALENDAR_TODAY, CSS_CALENDAR_BEFORE, CSS_CALENDAR_BETWEEN);
if (item.isBefore(fromDate.getValue())) {
getStyleClass().add(CSS_CALENDAR_BEFORE);
} else if (item.isBefore(toDate.getValue()) || item.isEqual(toDate.getValue())) {
getStyleClass().add(CSS_CALENDAR_BETWEEN);
}
if (item.isEqual(controller.currentDate())) {
getStyleClass().add(CSS_CALENDAR_TODAY);
setTooltip(todayTooltip);
} else {
setTooltip(null);
}
}
};
}
};
converter = new DateConverter();
fromDateListener = (observableValue, oldValue, newValue) -> {
if (newValue == null) {
// Restting old value and cancel..
setDateWithoutFiringEvent(oldValue, fromDate);
return;
}
controller.fromDateProperty().set(newValue);
};
toDateListener = (observableValue, oldValue, newValue) -> {
if (newValue == null) {
// Restting old value and cancel..
setDateWithoutFiringEvent(oldValue, toDate);
return;
}
controller.toDateProperty().set(newValue);
};
}
/**
* Changes the date on {#code datePicker} without fire {#code onAction} event.
*/
private void setDateWithoutFiringEvent(LocalDate newDate, DatePicker datePicker) {
final EventHandler<ActionEvent> onAction = datePicker.getOnAction();
datePicker.setOnAction(null);
datePicker.setValue(newDate);
datePicker.setOnAction(onAction);
}
public void bindAndRegisterHandlers() {
toDate.setDayCellFactory(toDateCellFactory);
fromDate.setDayCellFactory(fromDateCellFactory);
fromDate.valueProperty().addListener(fromDateListener);
fromDate.setConverter(converter);
toDate.valueProperty().addListener(toDateListener);
toDate.setConverter(converter);
}
public void makeLayout() {
setHgap(6);
add(fromLabel, 0, 0);
add(fromDate, 1, 0);
add(toLabel, 2, 0);
add(toDate, 3, 0);
fromDate.setPrefWidth(120);
toDate.setPrefWidth(120);
fromLabel.setId("calendar-label");
toLabel.setId("calendar-label");
}
public void i18n() {
// i18n code replaced with
fromDate.setPromptText("dd.mm.yyyy");
toDate.setPromptText("dd.mm.yyyy");
fromLabel.setText("From");
toLabel.setText("To");
todayTooltip.setText("Today");
}
public void initComponent() {
fromDate.setTooltip(null); // Ønsker ikke tooltip
setDateWithoutFiringEvent(controller.currentDate(), fromDate);
fromDate.setShowWeekNumbers(DISPLAY_WEEK_NUMBER);
toDate.setTooltip(null); // Ønsker ikke tooltip
setDateWithoutFiringEvent(controller.currentDate(), toDate);
toDate.setShowWeekNumbers(DISPLAY_WEEK_NUMBER);
}
}
/** period-picker.css goes udner resources (using maven) **/
.date-picker {
/* -fx-font-size: 11pt;*/
}
.calendar-before {
}
.calendar-between {
-fx-background-color: #bce9ff;
}
.calendar-between:hover {
-fx-background-color: rgb(0, 150, 201);
}
.calendar-between:focused {
-fx-background-color: rgb(0, 150, 201);
}
.calendar-today {
-fx-background-color: rgb(255, 218, 111);
}
.calendar-today:hover {
-fx-background-color: rgb(0, 150, 201);
}
.calendar-today:focused {
-fx-background-color: rgb(0, 150, 201);
}
#calendar-label {
-fx-font-style: italic;
-fx-fill: rgb(75, 75, 75);
-fx-font-size: 11;
}
I think you are already in the right track... DateCell and drag could work, since the popup is not closed if a dragging event is detected or when it ends. That gives you the opportunity to track the cells selected by the user.
This is a quick hack, but it may help you with the range selection.
First it will get the content and a list of all the cells within the displayed month, adding a listener to drag events, marking as the first cell that where the drag starts, and selecting all the cells within this first cell and the cell under the actual mouse position, deselecting the rest.
After the drag event finished, the selected range is shown on the console. And you can start all over again, until the popup is closed.
private DateCell iniCell=null;
private DateCell endCell=null;
#Override
public void start(Stage primaryStage) {
DatePicker datePicker=new DatePicker();
datePicker.setValue(LocalDate.now());
Scene scene = new Scene(new AnchorPane(datePicker), 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
datePicker.showingProperty().addListener((obs,b,b1)->{
if(b1){
DatePickerContent content = (DatePickerContent)((DatePickerSkin)datePicker.getSkin()).getPopupContent();
List<DateCell> cells = content.lookupAll(".day-cell").stream()
.filter(ce->!ce.getStyleClass().contains("next-month"))
.map(n->(DateCell)n)
.collect(Collectors.toList());
content.setOnMouseDragged(e->{
Node n=e.getPickResult().getIntersectedNode();
DateCell c=null;
if(n instanceof DateCell){
c=(DateCell)n;
} else if(n instanceof Text){
c=(DateCell)(n.getParent());
}
if(c!=null && c.getStyleClass().contains("day-cell") &&
!c.getStyleClass().contains("next-month")){
if(iniCell==null){
iniCell=c;
}
endCell=c;
}
if(iniCell!=null && endCell!=null){
int ini=(int)Math.min(Integer.parseInt(iniCell.getText()),
Integer.parseInt(endCell.getText()));
int end=(int)Math.max(Integer.parseInt(iniCell.getText()),
Integer.parseInt(endCell.getText()));
cells.stream()
.forEach(ce->ce.getStyleClass().remove("selected"));
cells.stream()
.filter(ce->Integer.parseInt(ce.getText())>=ini)
.filter(ce->Integer.parseInt(ce.getText())<=end)
.forEach(ce->ce.getStyleClass().add("selected"));
}
});
content.setOnMouseReleased(e->{
if(iniCell!=null && endCell!=null){
System.out.println("Selection from "+iniCell.getText()+" to "+endCell.getText());
}
endCell=null;
iniCell=null;
});
}
});
}
And this is how it looks like:
For now this doesn't update the textfield, as this involves using a custom formatter.
EDIT
I've added a custom string converter to show the range on the textfield, after a selection is done, and also to select a range if a valid one is entered.
This is not bullet proof, but it works as a proof of concept.
private DateCell iniCell=null;
private DateCell endCell=null;
private LocalDate iniDate;
private LocalDate endDate;
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d.MM.uuuu", Locale.ENGLISH);
#Override
public void start(Stage primaryStage) {
DatePicker datePicker=new DatePicker();
datePicker.setValue(LocalDate.now());
datePicker.setConverter(new StringConverter<LocalDate>() {
#Override
public String toString(LocalDate object) {
if(iniDate!=null && endDate!=null){
return iniDate.format(formatter)+" - "+endDate.format(formatter);
}
return object.format(formatter);
}
#Override
public LocalDate fromString(String string) {
if(string.contains("-")){
try{
iniDate=LocalDate.parse(string.split("-")[0].trim(), formatter);
endDate=LocalDate.parse(string.split("-")[1].trim(), formatter);
} catch(DateTimeParseException dte){
return LocalDate.parse(string, formatter);
}
return iniDate;
}
return LocalDate.parse(string, formatter);
}
});
Scene scene = new Scene(new AnchorPane(datePicker), 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
datePicker.showingProperty().addListener((obs,b,b1)->{
if(b1){
DatePickerContent content = (DatePickerContent)((DatePickerSkin)datePicker.getSkin()).getPopupContent();
List<DateCell> cells = content.lookupAll(".day-cell").stream()
.filter(ce->!ce.getStyleClass().contains("next-month"))
.map(n->(DateCell)n)
.collect(Collectors.toList());
// select initial range
if(iniDate!=null && endDate!=null){
int ini=iniDate.getDayOfMonth();
int end=endDate.getDayOfMonth();
cells.stream()
.forEach(ce->ce.getStyleClass().remove("selected"));
cells.stream()
.filter(ce->Integer.parseInt(ce.getText())>=ini)
.filter(ce->Integer.parseInt(ce.getText())<=end)
.forEach(ce->ce.getStyleClass().add("selected"));
}
iniCell=null;
endCell=null;
content.setOnMouseDragged(e->{
Node n=e.getPickResult().getIntersectedNode();
DateCell c=null;
if(n instanceof DateCell){
c=(DateCell)n;
} else if(n instanceof Text){
c=(DateCell)(n.getParent());
}
if(c!=null && c.getStyleClass().contains("day-cell") &&
!c.getStyleClass().contains("next-month")){
if(iniCell==null){
iniCell=c;
}
endCell=c;
}
if(iniCell!=null && endCell!=null){
int ini=(int)Math.min(Integer.parseInt(iniCell.getText()),
Integer.parseInt(endCell.getText()));
int end=(int)Math.max(Integer.parseInt(iniCell.getText()),
Integer.parseInt(endCell.getText()));
cells.stream()
.forEach(ce->ce.getStyleClass().remove("selected"));
cells.stream()
.filter(ce->Integer.parseInt(ce.getText())>=ini)
.filter(ce->Integer.parseInt(ce.getText())<=end)
.forEach(ce->ce.getStyleClass().add("selected"));
}
});
content.setOnMouseReleased(e->{
if(iniCell!=null && endCell!=null){
iniDate=LocalDate.of(datePicker.getValue().getYear(),
datePicker.getValue().getMonth(),
Integer.parseInt(iniCell.getText()));
endDate=LocalDate.of(datePicker.getValue().getYear(),
datePicker.getValue().getMonth(),
Integer.parseInt(endCell.getText()));
System.out.println("Selection from "+iniDate+" to "+endDate);
datePicker.setValue(iniDate);
int ini=iniDate.getDayOfMonth();
int end=endDate.getDayOfMonth();
cells.stream()
.forEach(ce->ce.getStyleClass().remove("selected"));
cells.stream()
.filter(ce->Integer.parseInt(ce.getText())>=ini)
.filter(ce->Integer.parseInt(ce.getText())<=end)
.forEach(ce->ce.getStyleClass().add("selected"));
}
endCell=null;
iniCell=null;
});
}
});
}
By using this answer here: https://stackoverflow.com/a/60618476/9278333
I was able to create this date range selector without the use of a private api:
Usage:
MultiDatePicker multiDatePicker = new MultiDatePicker().withRangeSelectionMode();
DatePicker rangePicker = multiDatePicker.getDatePicker();
import javafx.collections.FXCollections;
import javafx.scene.control.*;
import javafx.util.StringConverter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import static java.time.temporal.ChronoUnit.DAYS;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import javafx.collections.ObservableSet;
import javafx.event.EventHandler;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
public class MultiDatePicker
{
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private final ObservableSet<LocalDate> selectedDates;
private final DatePicker datePicker;
public MultiDatePicker()
{
this.selectedDates = FXCollections.observableSet(new TreeSet<>());
this.datePicker = new DatePicker();
setUpDatePicker();
}
public MultiDatePicker withRangeSelectionMode()
{
EventHandler<MouseEvent> mouseClickedEventHandler = (MouseEvent clickEvent) ->
{
if (clickEvent.getButton() == MouseButton.PRIMARY)
{
if (!this.selectedDates.contains(this.datePicker.getValue()))
{
this.selectedDates.add(datePicker.getValue());
this.selectedDates.addAll(getRangeGaps((LocalDate) this.selectedDates.toArray()[0], (LocalDate) this.selectedDates.toArray()[this.selectedDates.size() - 1]));
} else
{
this.selectedDates.remove(this.datePicker.getValue());
this.selectedDates.removeAll(getTailEndDatesToRemove(this.selectedDates, this.datePicker.getValue()));
this.datePicker.setValue(getClosestDateInTree(new TreeSet<>(this.selectedDates), this.datePicker.getValue()));
}
}
this.datePicker.show();
clickEvent.consume();
};
this.datePicker.setDayCellFactory((DatePicker param) -> new DateCell()
{
#Override
public void updateItem(LocalDate item, boolean empty)
{
super.updateItem(item, empty);
//...
if (item != null && !empty)
{
//...
addEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedEventHandler);
} else
{
//...
removeEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedEventHandler);
}
if (!selectedDates.isEmpty() && selectedDates.contains(item))
{
if (Objects.equals(item, selectedDates.toArray()[0]) || Objects.equals(item, selectedDates.toArray()[selectedDates.size() - 1]))
{
setStyle("-fx-background-color: rgba(3, 169, 1, 0.7);");
} else
{
setStyle("-fx-background-color: rgba(3, 169, 244, 0.7);");
}
} else
{
setStyle(null);
}
}
});
return this;
}
public ObservableSet<LocalDate> getSelectedDates()
{
return this.selectedDates;
}
public DatePicker getDatePicker()
{
return this.datePicker;
}
private void setUpDatePicker()
{
this.datePicker.setConverter(new StringConverter<LocalDate>()
{
#Override
public String toString(LocalDate date)
{
return (date == null) ? "" : DATE_FORMAT.format(date);
}
#Override
public LocalDate fromString(String string)
{
return ((string == null) || string.isEmpty()) ? null : LocalDate.parse(string, DATE_FORMAT);
}
});
EventHandler<MouseEvent> mouseClickedEventHandler = (MouseEvent clickEvent) ->
{
if (clickEvent.getButton() == MouseButton.PRIMARY)
{
if (!this.selectedDates.contains(this.datePicker.getValue()))
{
this.selectedDates.add(datePicker.getValue());
} else
{
this.selectedDates.remove(this.datePicker.getValue());
this.datePicker.setValue(getClosestDateInTree(new TreeSet<>(this.selectedDates), this.datePicker.getValue()));
}
}
this.datePicker.show();
clickEvent.consume();
};
this.datePicker.setDayCellFactory((DatePicker param) -> new DateCell()
{
#Override
public void updateItem(LocalDate item, boolean empty)
{
super.updateItem(item, empty);
//...
if (item != null && !empty)
{
//...
addEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedEventHandler);
} else
{
//...
removeEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedEventHandler);
}
if (selectedDates.contains(item))
{
setStyle("-fx-background-color: rgba(3, 169, 244, 0.7);");
} else
{
setStyle(null);
}
}
});
}
private static Set<LocalDate> getTailEndDatesToRemove(Set<LocalDate> dates, LocalDate date)
{
TreeSet<LocalDate> tempTree = new TreeSet<>(dates);
tempTree.add(date);
int higher = tempTree.tailSet(date).size();
int lower = tempTree.headSet(date).size();
if (lower <= higher)
{
return tempTree.headSet(date);
} else if (lower > higher)
{
return tempTree.tailSet(date);
} else
{
return new TreeSet<>();
}
}
private static LocalDate getClosestDateInTree(TreeSet<LocalDate> dates, LocalDate date)
{
Long lower = null;
Long higher = null;
if (dates.isEmpty())
{
return null;
}
if (dates.size() == 1)
{
return dates.first();
}
if (dates.lower(date) != null)
{
lower = Math.abs(DAYS.between(date, dates.lower(date)));
}
if (dates.higher(date) != null)
{
higher = Math.abs(DAYS.between(date, dates.higher(date)));
}
if (lower == null)
{
return dates.higher(date);
} else if (higher == null)
{
return dates.lower(date);
} else if (lower <= higher)
{
return dates.lower(date);
} else if (lower > higher)
{
return dates.higher(date);
} else
{
return null;
}
}
private static Set<LocalDate> getRangeGaps(LocalDate min, LocalDate max)
{
Set<LocalDate> rangeGaps = new LinkedHashSet<>();
if (min == null || max == null)
{
return rangeGaps;
}
LocalDate lastDate = min.plusDays(1);
while (lastDate.isAfter(min) && lastDate.isBefore(max))
{
rangeGaps.add(lastDate);
lastDate = lastDate.plusDays(1);
}
return rangeGaps;
}
}

Google maps API v2 Android, not drawing polygon when offline

I have a test application that I draw a Polygon using google maps API.
The problem is that, when I have no cache of any maps (new installed application) the Polygon does not draw.
Its not a problem not having the maps loaded, but I do need the Polygons drawn in my screen.
Is there a way I can do that?
Sry for my bad english
Heres the code I have:
package ngvl.testegmaps_v2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import ngvl.testegmaps_v2.VO.GeoPosicionamento;
import ngvl.testegmaps_v2.VO.Layer;
import ngvl.testegmaps_v2.VO.Secao;
import ngvl.testegmaps_v2.VO.Talhao;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Polygon;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class MainActivity extends FragmentActivity {
private List<Secao> secoes;
private List<Polygon> poligonos = new ArrayList<Polygon>();
private HashMap<String,Object[]> informacoes = new HashMap<String,Object[]>();
private GoogleMap map;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
map = fragment.getMap();
map.getUiSettings().setRotateGesturesEnabled(false);
// Setting a click event handler for the map
LatLng latLng = new LatLng(-20.9957152, -47.3241304);
// map.addMarker(new
// MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)).title("Av. Paulista").snippet("São Paulo"));
configuraPosicao(map, latLng);
Button button = (Button)findViewById(R.id.button1);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
}
private void configuraPosicao(GoogleMap map, LatLng latLng) {
/*
* 3D map.moveCamera( CameraUpdateFactory.newLatLngZoom(latLng, 15));
* map.animateCamera( CameraUpdateFactory.zoomTo(10), 2000, null);
*
* CameraPosition cameraPosition = new CameraPosition.Builder()
* .target(latLng) .zoom(17) .bearing(90) .tilt(45) .build();
*
* map.animateCamera( CameraUpdateFactory.newCameraPosition(
* cameraPosition));
*/
map.setMapType(GoogleMap.MAP_TYPE_NONE);
// map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17.0f));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
try {
String json = readFileAsString("geo.json");
Gson gson = new Gson();
this.secoes = gson.fromJson(json, new TypeToken<List<Secao>>() {
}.getType());
json = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
escrevePoligons(map);
}
private String readFileAsString(String fileName) throws IOException {
InputStream is = getAssets().open(fileName);
if (is != null) {
StringBuilder sb = new StringBuilder();
String line;
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8"));
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
} finally {
is.close();
}
return sb.toString();
} else {
return "";
}
}
private void escrevePoligons(GoogleMap map) {
float stroke = (float) 1.5;
for (Secao secao : secoes) {
for (Talhao talhao : secao.getTalhoes()) {
for (Layer layer : talhao.getLayers()) {
// PolygonOptions rectOptions = new PolygonOptions();
List<LatLng> latlngs = new ArrayList<LatLng>();
for (GeoPosicionamento geoPosicionamento : layer.getGeoPosicionamentos()) {
latlngs.add(new LatLng(geoPosicionamento.getLatitude()
.setScale(7, BigDecimal.ROUND_HALF_EVEN)
.doubleValue(), geoPosicionamento
.getLongitude()
.setScale(7, BigDecimal.ROUND_HALF_EVEN)
.doubleValue()));
}
int color = 0x1F00FF00;
int color2 = 0x5F000000;
PolygonOptions polygonOptions = new PolygonOptions()
.fillColor(color).addAll(latlngs)
.strokeColor(color2).strokeWidth(stroke);
Polygon p = map.addPolygon(polygonOptions);
poligonos.add(p);
informacoes.put( p.getId(), new Object[]{ secao, talhao , layer } );
//System.out.println(polygonOptions.getPoints());
polygonOptions = null;
latlngs = null;
}
}
}
this.secoes = null;
// String mUrl =
// "https://khms0.google.com.br/kh/v=124&src=app&z={z}&x={x}&y={y}";
// MyUrlTileProvider mTileProvider = new MyUrlTileProvider(256, 256,
// mUrl);
// mTileProvider.tilesRange();
// map.addTileOverlay(new
// TileOverlayOptions().tileProvider(mTileProvider).zIndex(-1f));
//String mUrl = "http://a.tile.openstreetmap.org/{z}/{x}/{y}.png";
//MyUrlTileProvider mTileProvider = new MyUrlTileProvider(256, 256, mUrl);
//map.addTileOverlay(new TileOverlayOptions().tileProvider(mTileProvider).zIndex(-1f));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-20.9957152, -47.3241304), 14));
// TileProvider tileProvider = TileProviderFactory.getTileProvider();
// map.addTileOverlay(new
// TileOverlayOptions().tileProvider(tileProvider));
// map.moveCamera(CameraUpdateFactory.newLatLngZoom(new
// LatLng(-20.9957152, -47.3241304), 15));
map.setOnMapClickListener(new OnMapClickListener()
{
public void onMapClick(LatLng point)
{
Polygon p = isPointInPolygon(point);
if( p != null){
p.setFillColor(getRandomColor());
Object[] clicado = informacoes.get( p.getId() );
Secao secao_clicada = (Secao) clicado[0];
Talhao talhao_clicada = (Talhao) clicado[1];
Layer layer_clicada = (Layer) clicado[2];
//System.out.println(secao_clicada);
//System.out.println(talhao_clicada);
//System.out.println(layer_clicada);
//System.out.println("=======================");
StringBuilder texto = new StringBuilder();
texto.append("Seção: " + secao_clicada.getDesc() + "\n");
texto.append("Talhão: " + talhao_clicada.getTalhao() + "\n");
texto.append("Variedade: " + talhao_clicada.getVariedade() + " - " + talhao_clicada.getDescVariedade() + "\n");
texto.append("Layer: " + layer_clicada.getSequencia() + "\n");
//Toast.makeText(MainActivity.this, texto , Toast.LENGTH_LONG).show();
addMarker(point,texto);
}//else
//Toast.makeText(MainActivity.this,"Clicou fora da Área de um Poligono", Toast.LENGTH_LONG).show();
}
});
}
public void addMarker(LatLng point, StringBuilder texto) {
/*map.addMarker(new MarkerOptions().position(point).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))
.title("Caracteristicas: ")
.snippet( texto );
*/
Toast.makeText(MainActivity.this, texto , Toast.LENGTH_LONG).show();
}
private Polygon isPointInPolygon(LatLng tap) {
for( Polygon p : poligonos){
int intersectCount = 0;
List<LatLng> vertices = p.getPoints();
for(int j=0; j<vertices.size()-1; j++) {
if( rayCastIntersect(tap, vertices.get(j), vertices.get(j+1)) ) {
intersectCount++;
}
}
if(((intersectCount % 2) == 1)){
return p;
}
}
return null;// odd = inside, even = outside;
}
private boolean rayCastIntersect(LatLng tap, LatLng vertA, LatLng vertB) {
double aY = vertA.latitude;
double bY = vertB.latitude;
double aX = vertA.longitude;
double bX = vertB.longitude;
double pY = tap.latitude;
double pX = tap.longitude;
if ( (aY>pY && bY>pY) || (aY<pY && bY<pY) || (aX<pX && bX<pX) ) {
return false; // a and b can't both be above or below pt.y, and a or b must be east of pt.x
}
double m = (aY-bY) / (aX-bX); // Rise over run
double bee = (-aX) * m + aY; // y = mx + b
double x = (pY - bee) / m; // algebra is neat!
return x > pX;
}
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-20.9957152, -47.3241304), 14));
}
};
public int getRandomColor() {
int color;
Random rnd = new Random();
color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256),
rnd.nextInt(256));
return color;
}
}
Setting map type to MAP_TYPE_NONE like example above does not solve the problem
I will this as marked solved by using Maps Forge Open Source API
If someone did with Google Maps Api please share and I would change the answer.
The answer I found is that its impossible to render or access anything without rendering the map first (online or via cache)
This is actually a bug of GoogleMaps Api v2 for Android.
It is referenced here:
https://code.google.com/p/gmaps-api-issues/issues/detail?id=5017
Star it if you want to accelerate the bug fix!

Java TimerTask , wont stop when cancel is called

So...
I'm creating a plugin.
I have a main Class called Basics
Globally in Basics I create:
static Timer enterdungeon = new Timer();
static Timer finddungeon = new Timer();
static Timer lootdungeon = new Timer();
Also I have a class named task
the enterdungeon timer is a fixed period of time, and seems to work as expected when used.
As is the same for thee lootdungeon timer.
The finddungeon timer can be interrupted IF an event in basics is triggered.
The event DOES trigger fine
the top line in this event is:
finddungeon.cancel();
after it starts the lootdungeon timer.
the problem is the finddungeon timer does not cancel, it continues to run, below is the task class:
import java.util.TimerTask;
import me.boduzapho.Basics.DoWarp.Returner;
import org.bukkit.entity.Player;
public class task extends TimerTask
{
private final Player _player;
private final int ticks;
private int cnt = 0;
private final int _sec;
private final String _message;
public task(Player player, int sec, String message)
{
this._player = player;
this._sec = sec;
this._message = message;
this.ticks = sec;
}
private void timetoloot(Player p)
{
p.sendMessage("SUCCESS! Nice Job, Enjoy the loot!");
Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx,Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
}
private void failedwhiteblock(Player p)
{
p.sendMessage("FAIL! You did not find the white block. Sending you back. TRY AGAIN!");
Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
}
private void enterdungeon(Player p)
{
Basics.Stage.setLine(3, "Off you Go!");
Basics.Stage.update();
Basics.Stage.setLine(0, "");
Basics.Stage.setLine(1, "");
Basics.Stage.setLine(2, "");
Basics.Stage.setLine(3, "");
Basics.Stage.update();
Basics.cDoClear(p);
Basics.cDoSpawners(p);
Basics.cDoRed(p);
Returner loc1 = DoWarp.getwarp("dstart", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
Basics.DungeonPlayer = p;
p.sendMessage("Welcome to the Dungeon, you have 1 minuite to locate and click the white block.");
p.sendMessage("If you fail you will be returned to spawn. If you find it the treasures will be revieled");
p.sendMessage("and the monsters banished for 1 min so you can loot the chests! After which you will");
p.sendMessage("Be warped back to spawn with your Loot!");
Basics.finddungeon.schedule(new task(_player, 30, "Time left to find the WHITE block :"), 0, 1000);
Basics.enterdungeon.cancel();
}
#Override
public void run()
{
while (cnt < ticks)
{
try
{
Thread.sleep(1 * 1000);
_player.sendMessage(_message + " " + Integer.toString(_sec - cnt));
++cnt;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
_player.sendMessage("Done!");
if (_message == "Time left:")
{
enterdungeon(_player);
}
if (_message == "Time left to find the WHITE block :")
{
failedwhiteblock(_player);
}
if (_message == "Time left to LOOT:")
{
timetoloot(_player);
}
//
return;
}
}
Here is the function called in Basics (main class) that is supposed to cancel the finddungeon timer.
// white block in dungeon
if (DungeonPlayer == player)
{
if ((block != null) && (block.getType() == Material.WOOL))
{
player.sendMessage("Canceling finddungeon from Basics");
finddungeon.cancel();
cDoClear(player);
cDoChests(player);
player.sendMessage("Congradulations! Time to Loot your rewards for finding the White Block!");
Timer lootdungeon = new Timer();
lootdungeon.schedule(new task(player, 10, "Time left to LOOT:"), 0, 1000);
return;
// ***
}
}
Can anyone shed any light on this?
Cause TimerTask.cancel doesn't do anything to the active task, it just clears the scheduler. You'll have to override cancel method, or just use this as a starting point:
class MyTimerTask extends TimerTask {
private volatile Thread thread;
#Override
public void run() {
thread = Thread.currentThread();
//do your task and keep your eye on InterruptedException when doing Sleeps, Waits
//also check Thread.interrupted()
}
public boolean cancel() {
Thread thread = this.thread;
if (thread != null) {
thread.interrupt();
}
return super.cancel();
}
}

How can I exercise the quick assist feature of Eclipse using SWTBot?

I'd like to use SWTBot to inline a local variable via the quick assist menu. My SWTBot test pops up the quick assist menu, but it fails to select the proposal item. I've created a minimal project on GitHub that demonstrates this problem and opened an issue that describes the problem in detail.
I had the same problem with the auto-completion menu and the only workaround I found was to implement my own autoComplete methods. You can easily do something similar for quick assist. My code has been tested under windows and unix systems:
package aaa.bbb.ccc;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
import java.util.List;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swtbot.swt.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.junit.Assert;
public abstract class AutoCompletionHelper {
public static void autoCompleteWithFirstMatchingProposal(SWTWorkbenchBot bot) {
SWTBotTable proposalsTable = showCompletionProposalsTable(bot);
Assert.assertTrue("No completion proposals found", proposalsTable.rowCount() > 0);
selectProposal(proposalsTable, 0);
}
public static void autoCompleteWithProposal(SWTWorkbenchBot bot, String completionProposal) {
SWTBotTable proposalsTable = showCompletionProposalsTable(bot);
int rowCount = proposalsTable.rowCount();
int index = -1;
int matchingProposalsCount = 0;
for (int i = 0; i < rowCount; i++) {
if (proposalsTable.cell(i, 0).startsWith(completionProposal)) {
index = i;
matchingProposalsCount++;
}
}
Assert.assertFalse("No completion proposals matching '" + completionProposal + "'", matchingProposalsCount == 0);
Assert.assertFalse("Multiple completion proposals matching '" + completionProposal + "'", matchingProposalsCount > 1);
selectProposal(proposalsTable, index);
}
private static SWTBotTable showCompletionProposalsTable(EclipseBot bot) {
bot.pressShortcut(KeyStroke.getInstance(SWT.CTRL, 0), KeyStroke.getInstance(0, SWT.SPACE));
bot.sleep(100); //Wait for auto-completion shell to be displayed
List<Shell> shells = bot.shells("");
Table proposalsTable = null;
long timeout = SWTBotPreferences.TIMEOUT;
SWTBotPreferences.TIMEOUT = 200;
boolean findInvisibleControls = bot.getFinder().shouldFindInvisibleControls();
bot.getFinder().setShouldFindInvisibleControls(true);
try {
for (Shell shell : shells) {
try {
proposalsTable = bot.widget(widgetOfType(Table.class), shell);
} catch (WidgetNotFoundException ex) {
continue;
}
break;
}
} finally {
bot.getFinder().setShouldFindInvisibleControls(findInvisibleControls);
SWTBotPreferences.TIMEOUT = timeout;
}
if (proposalsTable == null) {
throw new RuntimeException("Did not find any completion proposals table ...");
}
return new SWTBotTable(proposalsTable);
}
private static void selectProposal(final SWTBotTable proposalsTable, final int proposalIndex) {
UIThreadRunnable.asyncExec(new VoidResult() {
#Override
public void run() {
Table table = proposalsTable.widget;
table.setSelection(proposalIndex);
Event event = new Event();
event.type = SWT.Selection;
event.widget = table;
event.item = table.getItem(proposalIndex);
table.notifyListeners(SWT.Selection, event);
table.notifyListeners(SWT.DefaultSelection, event);
}
});
}
}