using CSS to change node design - css

I dont know what I'am doing wrong with adding CSS style to node.
I have a main application window. Then I click menu item and another modal window opens as below(ModalWindow extends Stage):
FXMLLoader loader = new FXMLLoader(getClass().getResource(CONSTANTS.ROOT_USER_EDIT.string));
BorderPane editPane;
try {
editPane = new BorderPane(loader.load());
ModalWindow editWindow = new ModalWindow(Main.mainStage, editPane, "Edit user");
//its new stage with new scene, so we need to load this file again
editWindow.getScene().getStylesheets().add(getClass().getResource(CONSTANTS.CSS_PATH.string).toExternalForm());
UserData userData = (UserData)usersTable.getSelectionModel().getSelectedItem();
UserEditWindowController userEditWindowController = loader.getController();
userEditWindowController.fillWithData(userData);
editWindow.initModality(Modality.APPLICATION_MODAL);
editWindow.showAndWait();
} catch (IOException exception) {
ExceptionDialog exceptionDialog = new ExceptionDialog("Couldn't load UserEditWindow",exception);
exceptionDialog.showAndWait();
}
this CSS file is added:
#greenInfoTip {
-fx-graphic-text-gap: 20;
-fx-font-size: 44.0px ;
-fx-background: green;
-fx-background-color: rgb(128,255,128);
}
And I try to do this in root controller class:
infoTip.setId("greenInfoTip");
but with no effect. Is there something I'm doing wrong?
EDIT ItachiUchiha here is precisely what it looks like:
method is inside UserEditWindowController class:
#FXML
private void buttSaveAction(ActionEvent event){
//check if login and password doesn't contain spaces and is 4-16 characters long
String login = textFLogin.getText();
String password = textFPassword.getText();
boolean hasLoginWhiteSpace = isContainingWhiteSpace(login);
boolean hasPasswordWhiteSpace = isContainingWhiteSpace(password);
boolean isLoginMoreThan3 = (login.length() > 3)? true : false;
boolean isLoginLessThan17 = (login.length() < 17)? true : false;
boolean isPasswordMoreThan3 = (password.length() > 3)? true : false;
boolean isPasswordLessThan17 = (password.length() < 17)? true : false;
InfoTip infoTip = new InfoTip();
if( hasLoginWhiteSpace == false){
if( hasPasswordWhiteSpace == false ){
if( isLoginMoreThan3 == true && isLoginLessThan17 == true){
if( isPasswordMoreThan3 == true && isPasswordLessThan17 == true ){
//========login and password are correct
String query = "UPDATE users SET login = ?, password = ? WHERE employee_id = ?;";
try( Connection connection = Main.dataSource.getConnection() ){
try( PreparedStatement preparedStatement = connection.prepareStatement(query) ){
preparedStatement.setString(1, login);
preparedStatement.setString(2, password);
preparedStatement.setInt(3, currentUser.getiD());
preparedStatement.executeUpdate();
currentUser.setLogin(login);
currentUser.setPassword(password);
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), "Saved");
}
}catch(Exception exception){
ExceptionDialog exceptionDialog = new ExceptionDialog("Error while loading data from database",exception);
exceptionDialog.showAndWait();
};
}else{ //password has less than 4 or more than 16 characters
infoTip.showTip(textFPassword, "no more than 16 and no less than 4 characters!");
}
}else{ //login has less than 4 or more than 16 characters
infoTip.showTip(textFLogin, "no more than 16 and no less than 4 characters!");
}
}else{ //password has white space
infoTip.showTip(textFPassword, "no spaces!");
}
}else{ //login has white space
infoTip.showTip(textFLogin, "no spaces!");
}
}
public class InfoTip {
private Tooltip infoTip;
public InfoTip(){
infoTip = new Tooltip();
}
private static Point2D getNodePos(Node node){ //getting node coordination on screen
Scene nodeScene = node.getScene();
final Point2D windowPos = new Point2D(nodeScene.getWindow().getX(), nodeScene.getWindow().getY());
final Point2D scenePos = new Point2D(nodeScene.getX(), nodeScene.getY());
final Point2D nodePos = node.localToScene(0.0, 0.0);
final Point2D nodePosOnScreen = new Point2D(windowPos.getX() + scenePos.getX() + nodePos.getX(),
windowPos.getY() + scenePos.getY() + nodePos.getY());
return nodePosOnScreen;
}
public void showTip(Node node, String text){
Point2D nodePosOnScreen = getNodePos(node);
infoTip = new Tooltip(text);
infoTip.setFont(new Font(15));
infoTip.setOpacity(0.9);
infoTip.setAutoFix(true);
infoTip.setAutoHide(true);
infoTip.show(node, nodePosOnScreen.getX()-30, nodePosOnScreen.getY() - 40);
}
public Tooltip getInfoTip(){
return infoTip;
}
}

The issue is with
infoTip = new Tooltip(text);
inside howTip(Node node, String text).
You are over-writing the old tooltip with id with a new object. Try using
infoTip.setText(text);

Related

Cefsharp Custom Prompt

How can i make custom Prompt?
I tried with code below..
public static string ShowDialog(string text, string caption) {
Form prompt = new Form() {
Width = 500,
Height = 150,
FormBorderStyle = FormBorderStyle.FixedDialog,
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(textBox);
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.AcceptButton = confirmation;
return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
}
And then am using it like below
public bool OnJSDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage) {
if(dialogType.ToString() == "Prompt") {
//Form prompt = ShowDialogClass.ShowDialog("as", "asd");
string promptValue = Components.ShowDialog("Test", "123");
if (promptValue != "") {
callback.Continue(true, promptValue);
} else {
callback.Continue(false, "");
};
};
But i am getting error.
System.InvalidOperationException: 'Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.'
return false;
}
How can i implement this dialog to show custom prompt?
Few months too late but, here you go.
You are trying to create a new Form(your prompt form) inside another thread. In this case your CEF browser thread that will create a object from class IJsDialogHandler will be on another thread than the prompt message thread so you have to Cross the thread to access it.
The way you do this is "Invoke"(saying something like "wo wo don't worry, i know what i'm doing"). When you use "Invoke" your asking for a witness, well that witness should have the same kind of capabilities as your prompt message box form so.... in this case form that creates the CEF browser. so the code should be something like this
public bool OnJSDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, CefJsDialogType dialogType, string messageText, string defaultPromptText, IJsDialogCallback callback, ref bool suppressMessage) {
if(dialogType.ToString() == "Prompt") {
if (ParentForm.InvokeRequired)
{
ParentForm.Invoke((MethodInvoker)delegate ()
{
string promptValue = Components.ShowDialog(messageText, "Prompt Message");
if (promptValue != "") {
callback.Continue(true, promptValue);
} else {
callback.Continue(false);
}
}
}
suppressMessage = false;
return true;
}
}
ParentForm should be changed to the name of the form that initialize the CEF browser.

Fill JavaFX combobox by javascript class (Nashorn)

I try to use my custom class which I have created in my script (the script is written in Nashorn) and after that I try to use this custom class to fill in as items in combobox. I know that if I want to see correct values in combobox that the class has to override method toString, but in this case I do not know much how can be overriden this method in my custom class written in Nahorn.
Below I provide my code where the variables cmbCategories is JavaFX combobox and CategoryItem which I try to use as object to fill in the items in combobox and display as category name.
I would appreciate any suggestion or ideas how can be this problem resolved.
var ClientBuilder = Java.type("javax.ws.rs.client.ClientBuilder")
var Platform = Java.type("javafx.application.Platform")
var Executors = Java.type("java.util.concurrent.Executors")
var Response = Java.type("javax.ws.rs.core.Response")
var String = Java.type("java.lang.String")
var List = Java.type("java.util.ArrayList")
Executors.newSingleThreadExecutor().execute(function () {
print("Calling for category data...")
var categoryData = ClientBuilder
.newClient()
.target(String.format("%s%s", "http://localhost:8080", "/client/action/categories"))
.request()
.get()
if(categoryData.getStatus() == Response.Status.OK.getStatusCode()) {
var categories = JSON.parse(categoryData.readEntity(String.class))
var categoryItems = new List();
for each (var category in categories) {
categoryItems.add(new CategoryItem(category.id, category.category))
}
Platform.runLater(function() {
cmbCategory.getItems().addAll(categoryItems);
});
} else {
print(categoryData.getEntity().toString());
}
})
function CategoryItem(id, name) {
this.id = id;
this.name = name;
this.toString = function () {
return this.name;
}
}
Use the ScriptEngine to retrieve an appropriate string in the cellValueFactory of the ComboBox.
Simplified example
#Override
public void start(Stage primaryStage) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByMimeType("application/javascript");
ComboBox<Object> comboBox = new ComboBox();
comboBox.setCellFactory(c -> new ListCell<Object>() {
#Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
Bindings bindings = new SimpleBindings();
bindings.put("a", item);
try {
// use script engine to retrieve text
setText(Objects.toString(engine.eval("a.name", bindings)));
} catch (ScriptException ex) {
setText("Error");
}
}
}
});
comboBox.setButtonCell(comboBox.getCellFactory().call(null));
Bindings b = new SimpleBindings();
b.put("cmbCategory", comboBox);
engine.eval("function CategoryItem(id, name) {this.id = id;this.name = name;}\n"
+"var Platform = Java.type(\"javafx.application.Platform\")\n"
+ "var categories = [new CategoryItem(1, 'a'), new CategoryItem(2, 'b'), new CategoryItem(3,'c')]\n"
+ "for each (var category in categories) {cmbCategory.getItems().add(category);}", b);
Scene scene = new Scene(new StackPane(comboBox));
primaryStage.setScene(scene);
primaryStage.show();
}
I don't see the purpose of using JavaScript for this though. Everything you do in the javascript code could be done from java code more efficiently...

set combobox value javafx dynamicaly

i hava probleme to fil a combobox ,
i create buttons dynamicaly where i set a event , whre i use a methode (from where i creat my list ) where i change the view , and set a combobox ,
createButton
private Button createButton(String text) {
Button button = new Button(text);
button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
button.setPrefSize(100, 100);
button.setOnAction(e -> {
try {
getImprByProduct(text);
} catch (IOException ex) {
Logger.getLogger(DuplicataController.class.getName()).log(Level.SEVERE, null, ex);
}
});
button.setId("btn");
System.out.println("************************** fin creation bouton");
return button;
}
getImprByProduct give me a list of my product wich i want to set in the combobox ,
public List<String> getImprByProduct(String prd) throws IOException {
//afficher Viewdupcontroller
ViewDupController dupController = new ViewDupController();
FXMLLoader fXMLLoader = new FXMLLoader();
fXMLLoader.load(getClass().getResource("/view/application/duplicata/ViewDuplicata.fxml").openStream());
if ((startPage1.global_Session.isOpen()) || (startPage1.global_Session.isConnected())) {
startPage1.global_Session.close();
}
startPage1.global_Session = HibernateUtil.getSessionFactory().openSession();
startPage1.global_Session.beginTransaction();
List<Impression> listImpr = impressionUse.getListImpression_SS();
for (Impression i : listImpr) {
Voucher v = new VoucherUse().getVoucherById(startPage1.global_Session, i.getIdVoucherDebutFk());
if (v.getProduit().getDesignation().equals(prd)) {
result.add(i);
}
}
startPage1.global_Session.getTransaction().commit();
startPage1.global_Session.close();
int p = 0;
for (Impression i : result) {
System.out.println("list des ID impression : " + i.getIdImpression());
list.add(i.getIdImpression().toString());
p++;
}
ListIterator li = list.listIterator();
while(li.hasNext()){
System.out.println("contenu list : " + li.next());
}
System.out.println("*********************************avant add fxml getroot affichage");
anch.getChildren().clear()
anch.getChildren().add(fXMLLoader.getRoot());
dupController.com(list); // i where i call the the methode in the controller of the new view ( of combobox )
return list;
}
dupController.com(list);
ObservableList obList = FXCollections.observableList(list);
combo1.getItems().clear();//where error is
combo1.setItems(obList);

fill javaFX treeView from database dynamically

I have a table on database (code, composant, parent) where each node has a parent (a parent is also a component code), I need to fill a treeView dynamically from a select
#FXML
private TreeView tree;//declaration of the treeView
HashMap<Integer, composant> node = new HashMap<>(); //for child nodes
HashMap<Integer, composant> pere = new HashMap<>(); //for parent nodes
composant c; //object from component class
private void fillTree(String idSys) {
String query = "SELECT * FROM composant WHERE id=?";
try {
ps = cnx.prepareStatement(query);
ps.setString(1, idSys);
rs = ps.executeQuery();
while (rs.next()) {
int code = rs.getInt("code");
String composant = rs.getString("composant");
int parent = rs.getInt("parent");
String niveau = rs.getString("niveau");
int id = rs.getInt("id");
c = new composant(code, composant, niveau, parent, id);
node.put(code, c);
pere.put(parent, c);
}
ps.close();
rs.close();
} catch (Exception e) {
System.err.println("Error" + e);
}
TreeItem<String> system = new TreeItem<>(sys);
//brows and fill parents node
for (Integer k : pere.keySet()) {
composant p = pere.get(k);
TreeItem<String> parent = new TreeItem<>();
parent.setValue(p.getComposant());
//brows and fill child hashmap
for (Integer i : node.keySet()) {
composant c = node.get(i);
TreeItem<String> noeud = new TreeItem<>();
noeud.setValue(c.getComposant());
if (c.getParent() == k) {
//if the parent = 1 it must attach to the root node
if (k == 1) {
system.getChildren().add(noeud);
} else {
parent.getChildren().add(noeud);
}
}
}
}
tree.setRoot(system);
}
when compiling nothing appear on the window
this is what I've got
I'm almost sure the logic of creating the tree structure is wrong.
It's best if you simply create the TreeItems and store them by code in a map. Then iterate over the map and add every child to it's parent:
Map<Integer, TreeItem<String>> itemById = new HashMap<>();
Map<Integer, Integer> parents = new HashMap<>();
while (rs.next()) {
int code = rs.getInt("code");
String composant = rs.getString("composant");
int parent = rs.getInt("parent");
String niveau = rs.getString("niveau");
int id = rs.getInt("id");
itemById.put(code, new TreeItem<>(composant));
parents.put(code, parent);
}
ps.close();
rs.close();
TreeItem<String> root = null;
for (Map.Entry<Integer, TreeItem<String>> entry : itemById.entrySet()) {
Integer key = entry.getKey();
Integer parent = parents.get(key);
if (parent.equals(key)) {
// in case the root item points to itself, this is it
root = entry.getValue();
} else {
TreeItem<String> parentItem = itemById.get(parent);
if (parentItem == null) {
// in case the root item has no parent in the resultset, this is it
root = entry.getValue();
} else {
// add to parent treeitem
parentItem.getChildren().add(entry.getValue());
}
}
}
tree.setRoot(root);
Note that the above code assumes there is a unique root stored in the table. in case the query returns a forest where each root should be added to the root item of the TreeView, simply initialize root with a item instead
TreeItem<String> root = new TreeItem<>();
and add the items to root instead of setting the root
// root = entry.getValue();
root.getChildren().add(entry.getValue());

How to accept mine if any conflicts occur while pull-rebase in JGit

I have a piece of code that does pull with rebase:
private void pullWithRebase(Git git) throws GitAPIException {
git.checkout().setName("master").call();
List<Ref> branches = git.branchList().setListMode(ListBranchCommand.ListMode.ALL).call();
String remoteMasterBranchName = "refs/remotes/origin/master";
for (Ref ref : branches) {
if (remoteMasterBranchName.equals(ref.getName())) {
PullResult result = git.pull().setRemoteBranchName("master").setRebase(true).call();
return;
}
}
}
However it doesn't work if any conflicts occur while merging. If they do occur, I want to accept mine
I ended up just merging two branches and directly resolving any conflicts by modifying files.
private static final String CONFLICT_HEAD_MARKER = "<<<<<<<";
private static final String CONFLICT_BORDER_MARKER = "=======";
private static final String CONFLICT_UPSTREAM_MARKER = ">>>>>>>";
private boolean acceptHead;
public void resolve(File file) throws IOException {
File temp = new File(file.getParent(), "temp" + System.currentTimeMillis());
try(BufferedReader reader = new BufferedReader(new FileReader(file));
BufferedWriter writer = new BufferedWriter(new FileWriter(temp))) {
String currentLine;
boolean removePartition = false;
while((currentLine = reader.readLine()) != null) {
if (currentLine.contains(CONFLICT_HEAD_MARKER)) {
removePartition = !acceptHead;
continue;
} else if (currentLine.contains(CONFLICT_BORDER_MARKER)) {
removePartition = acceptHead;
continue;
} else if (currentLine.contains(CONFLICT_UPSTREAM_MARKER)) {
removePartition = false;
continue;
}
if (!removePartition) {
writer.write(currentLine + System.getProperty("line.separator"));
}
}
}
FileUtils.forceDelete(file);
FileUtils.moveFile(temp, file);
}

Resources