How to set JavaFX-Alert into middle of actual monitor? - javafx

I've got a static method in a class without knowing anything about the Application, Scene oder Stage. But I want to show an Alert in the middle of the actual used monitor.
For example: My tool is on the right screen. I want to see the alert also there and not on the main screen.
My method:
private static Alert createAlert(AlertType type, String title, String header, String content) {
Alert alert = new Alert(type);
alert.setTitle(title);
if (!header.isEmpty()) {
alert.setHeaderText(header);
}
alert.setContentText(content);
alert.setResizable(true);
alert.setX(0); // set this into the middle of used monitor
alert.setY(0); //
return alert;
}
How can I get the actual stage, scene or whatever to get its x- and y-position and use these information for setting x and y of the alert?

Assuming you have a reference to the current window, you can find the screen that contains it (e.g. contains its center point) with:
Window currentWindow = ... ;
Point2D windowCenter = new Point2D(currentWindow.getX() + currentWindow.getWidth()/2,
currentWindow.getY() + currentWindow.getHeight()/2);
Screen currentScreen = Screen.getScreens().stream()
.filter(screen -> screen.getBounds().contains(windowCenter))
.findAny().get();
And then you can do
Rectangle2D screenBounds = currentScreen.getBounds();
double screenCenterX = screenBounds.getMinX() + screenBounds.getWidth()/2 ;
double screenCenterY = screenBounds.getMinY() + screenBounds.getHeight()/2 ;
and position the Alert accordingly...
You need to know the current window though; it will be impossible to do this without that information. For example, your application might have multiple windows with different ones on different screens; the notion of "current screen" is simply not well defined in a case like that.

Related

Xamarin Forms Entry boxes loses their cursor position with custom keypad

I am attempting to create a calculator app with a custom keypad using the MVVM pattern. The calculator has four entry boxes and I am suppressing the phone's keyboard from showing by using a custom renderer. I have noticed that the entrees lose their cursor position when I type numbers in an entry, change the cursor position manually by tapping in another position, and start typing again. When I start typing again, the initial character goes into the correct position, but any characters after that goes at the beginning of the string which means the cursor position is zero.
I cannot figure out what is resetting the cursor position. I am keeping track of the cursor position through binding. Here is a small snippet from my code below. So if EntryOne is Selected(Has Focus) and you start typing, the GetText method is called and I am passing in the cursor position by reference. The text that already exists in the Entry is separated into two parts. All the characters in front of the cursor position are part one and all the characters after the cursor position is part two. The parameter is the number the user pressed. All three strings are concatenated together to display the new text in the Entry box. If I use the phone’s keyboard I do not have this issue. So I know it is possible.
Please see the app attached and let me know if more info is needed. Any help would be greatly appreciated.
Thank you in advance!!!
EntryOneText = GetText(EntryOneText, parameter, ref _entryOneCursorIndex);
private string GetText(string text, string parameter, ref int cursorPosition)
{
if (!string.IsNullOrEmpty(text))
{
string partOne = text.Substring(0, cursorPosition);
string partTwo = text.Substring(cursorPosition, (text.Length - cursorPosition));
cursorPosition++;
return string.Format("{0}{1}{2}", partOne, parameter, partTwo);
}
cursorPosition++;
return parameter;
}
EntryCursorPositionTest
Thanks to Alessandro Caliaro. He provided an answer for me on the Xamarin Forms Forum.
private void EntryOne_Focused(object sender, FocusEventArgs e)
{
_mainViewModel.SelectedEntry = 1;
_mainViewModel.EntryOneCursorIndex = ((Entry)sender).CursorPosition;
}
public ICommand NumericCommand
{
get
{
return new Command<string>((string parameter) =>
{
if (!string.IsNullOrEmpty(parameter))
{
switch (SelectedEntry)
{
case 1:
if (EntryOneText == null)
EntryOneText = "";
int save = EntryOneCursorIndex;
EntryOneText = EntryOneText.Insert(save, parameter);
EntryOneCursorIndex = save + 1;
//EntryOneText = GetText(EntryOneText, parameter, ref _entryOneCursorIndex);
break;

JavaFX: How to take a node snapshot if the node bounds are set to maximum values?

I'm trying to take a snapshot of a custom pane (which I placed at the center of a BorderPane), but what I get each time is a blank PNG image. I've tried the same code with a button and it's snapshot is taken and saved successfully. I've checked the bounds and I noticed the bounds of the pane have maximum values (both the bounds in parent and bounds in local):
[minX:-9.9999997952E10, minY:-9.9999997952E10, minZ:0.0, width:1.99999995904E11, height:1.99999995904E11, depth:0.0, maxX:9.9999997952E10, maxY:9.9999997952E10, maxZ:0.0]
I think the cause for that is that the pane's layout is set so it fills the center space of the BorderPane. I also found the following in the documentation which supports my suspicion:
A pane's unbounded maximum width and height are an indication to the parent that it may be resized beyond its preferred size to fill whatever space is assigned to it.
This is the relevant code for taking a snapshot:
final WritableImage SNAPSHOT = mNodeToExport.snapshot(new SnapshotParameters(), null);
final File FILE = new File(mPathTextField.getText());
try {
ImageIO.write(SwingFXUtils.fromFXImage(SNAPSHOT, null), "png", FILE);
return FILE;
} catch (IOException exception) {
System.err.println("Error while exporting image of logicboard: " + exception.getMessage());
return null;
}
The contents of the snapshot right after creating it are:
debugging image which I think is pretty odd since it's width and height values should be way bigger than 1.
I've tried taking the snapshot of child nodes of the pane I'm trying to export and it works fine for the child nodes which have "non-infinite" bounds but returns the same image for the child node that has "infinite" bounds.
If the snapshot isn't taken correctly because of the "infinite" bound values, how can I temporarily change the pane's bounds for the snapshot? If the bounds are not the problem, then what might the problem be?
You can apparently pass a Rectangle2D that serves as the viewport for the snapshot. So the following does the job:
SnapshotParameters params = new SnapshotParameters();
params.setViewport(mLogicBoardView.getViewPort());
final WritableImage SNAPSHOT = mLogicBoardView.snapshot(params, null);
final File FILE = new File(mPathTextField.getText());
try {
ImageIO.write(SwingFXUtils.fromFXImage(SNAPSHOT, null), "png", FILE);
return FILE;
} catch (IOException exception) {
System.err.println("Error while exporting image of logicboard: " + exception.getMessage());
return null;
}
where I calculate the viewport manually in the getViewPort() function.

Failure to get the stage of a dialog

http://code.makery.ch/blog/javafx-dialogs-official/ shows how to get the stage of a JavaFX-8 dialog:
// Get the Stage.
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
Alas, this does not work for me: the dialog pane (although displayed) gives null on .getScene().
Is there any other easy way to get the stage or at least the scene of an open dialog window?
The background of the question is that, under certain circumstances, need to display an Alert to the user while keeping the underlying dialog window open. Currently, that does not work due to an invalid combination of Modality values, but that's a different topic.
Hard to say for sure if you post no context code but I think the problem is the timing. You need to get the stage before you showAndWait (or at least before the dialog is closed). Try this:
public static boolean showConfirmationDialog(String contentText, String headerText) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, contentText, ButtonType.YES, ButtonType.NO);
alert.setTitle("Test");
alert.setHeaderText(headerText);
Window alertWindow = alert.getDialogPane().getScene().getWindow();
System.out.println("alertWindow.getOpacity(): " + alertWindow.getOpacity());
Optional<ButtonType> result = alert.showAndWait();
//This would cause a NullPointerException at this point:
//alertWindow = alert.getDialogPane().getScene().getWindow();
//System.out.println("alertWindow.getOpacity(): " + alertWindow.getOpacity());
return (result.get() == ButtonType.YES);
}

Opening new window in WebDriver using C#

EDIT 4:
EDIT 3
EDIT 2
string currentWindow = driver.CurrentWindowHandle;
driver.SwitchTo().Window("");
string childTitle = driver.Title;
driver.SwitchTo().Window(currentWindow);
string parentTitle = driver.Title;
the above code gives me the same title for parent window or child window.
EDIT:
<a id="ctl00_ctl00_Features_ctl03_lnkPage" class="title" target="_blank" href="websiteaddress">Stay Around</a>
how to verify the title of a newly window open and once i verified then close the opened new window?
so in my page I have a link and click on the link and it opens a new window and now I am not sure how to verify the title of that window.
here is what i have done so far.
GoToMysiteUrl();
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
//it opens a new window
now i want to switch focus on the new window and verify the title and close the new window
back to the previous window.
The piece that most people miss when dealing with popup windows in IE is that a click on an element is asynchronous. That is to say, if you check the .WindowHandles property immediately after a click, you may lose the race condition, because you're checking for the existence of a new window before IE has had the chance to create it, and the driver has had a chance to register it exists.
Here's the C# code I would use to perform the same operation:
string foundHandle = null;
string originalWindowHandle = driver.CurrentWindowHandle;
// Get the list of existing window handles.
IList<string> existingHandles = driver.WindowHandles;
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
// Use a timeout. Alternatively, you could use a WebDriverWait
// for this operation.
DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(5));
while(DateTime.Now < timeout)
{
// This method uses LINQ, so it presupposes you are running on
// .NET 3.5 or above. Alternatively, it's possible to do this
// without LINQ, but the code is more verbose.
IList<string> currentHandles = driver.WindowHandles;
IList<string> differentHandles = currentHandles.Except(existingHandles).ToList();
if (differentHandles.Count > 0)
{
// There will ordinarily only be one handle in this list,
// so it should be safe to return the first one here.
foundHandle = differentHandles[0];
break;
}
// Sleep for a very short period of time to prevent starving the driver thread.
System.Threading.Thread.Sleep(250);
}
if (string.IsNullOrEmpty(foundHandle))
{
throw new Exception("didn't find popup window within timeout");
}
driver.SwitchToWindow(foundHandle);
// Do whatever verification on the popup window you need to, then...
driver.Close();
// And switch back to the original window handle.
driver.SwitchToWindow(originalWindowHandle);
Incidentally, if you're using the .NET bindings, you have access to a PopupWindowFinder class in the WebDriver.Support.dll assembly, which uses a very similar approach to the locating popup windows. You may find that class meets your needs exactly, and can use it without modification.
GoToMysiteUrl();
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
// Post above operation a new window would open as described in problem
// Get hold of Main window's handle
string currentWindow = Driver.CurrentWindowHandle;
// Switch to the newly opened window
Driver.SwitchTo().Window("Your Window Name");
// Perform required Actions/Assertions here and close the window
// Switch to Main window
Driver.SwitchTo().Window(currentWindow);

Mango Application Tile - remove back

This is a simple question, and a seemingly simple task but I can't find any info on how to accomplish what I need to do.
I have an application whose main tile (when pinned) sometimes needs to be the default, single sided tile and sometimes needs to have information displayed on the back of the tile. I can add the BackBackgroundImage, BackContent and BackTitle successfully from the ScheduledActionService, but I can't remove them when they are no longer required. This isn't a secondary tile so I can't remove it and re-create and re-add it.
Does anyone know if it is possible to revert a double-sided tile back to single-sided via code, and if so, how can I achieve that behaviour, please?
EDIT
The settings that get applied from the StandardTileData object are additive - if you only specify a title, for example, all other elements remain the same and only the title is updated. I have attempted to set the three parameters that appear on the back of the tile to null and had partial success. The effect is that the background image, title text and content text are all removed, but the tile still flips over to show a completely empty reverse side.
EDIT AGAIN
So, looking at the documentation, the tile back behaves differently to the front. Setting the back content or backtitle to string.Empty will remove those. All good there. However, it does say that "If set to an empty URI, the BackBackgroundImage will not be displayed.". How do I go about creating an empty Uri? I tried new Uri(string,Empty) but that throws an exception about trying to create an empty Uri - which is what I'm trying to do.
OK, I think I've got it, and it appears to be related to a change in the way tile data is handled...
Previously, setting a value to an empty string would have now effect in the tile. For eaxmple, setting title = string.Empty would leave the existing title in place. Now, though, it will blank out the title. That's good - it means I can remove BackTitle and BackContent string easily. We're half way there.
Now, to get rid of the BackBackgroundImage, the documentation states "If set to an empty URI, the BackBackgroundImage will not be displayed." - all good, except you can't create an empty Uri in any simple way. The one way I've made it work is to set it to a Uri value that doesn't exist, eg
BackBackgroundImage = new Uri("obviouslyMadeUpLocation", UriKind.Relative);
I would have expected that to throw an exception when you try to apply it to the tile, but it doesn't - it just clears the background image.
So that's it. All I appear to need to do is to call the following to unset these properties and put my tile back as it was.
private void ResetMyMainTile()
{
ShellTile tile = ShellTile.ActiveTiles.First();
StandardTileData data = new StandardTileData
{
BackBackgroundImage = new Uri("IDontExist",UriKind.Relative),
BackContent = string.Empty,
BackTitle = string.Empty
};
tile.Update(data);
}
This one works for me.
new Uri("Background.png", UriKind.RelativeOrAbsolute);
ShellTile TileToFind = ShellTile.ActiveTiles.First();
if (TileToFind != null)
{
StandardTileData NewTileData = new StandardTileData
{
Title ="Status",
BackgroundImage = new Uri("Background.png", UriKind.RelativeOrAbsolute),
Count = 0,
BackTitle = "",
BackBackgroundImage = new Uri("doesntexist.png", UriKind.RelativeOrAbsolute),
BackContent = ""
};
TileToFind.Update(NewTileData);
}
Try setting the whole tile (all details) again to everything as was before / is now but without the background details.
Update
Does this not work?:
ShellTile tile = ShellTile.ActiveTiles.First();
tile.Update(null);
or
tile.update(new StandardTileData());

Resources