I have a pretty big swing application and i want to make it remember sizes of all windows, jframes etc. So if user resized window how he likes, next time the window looks exact the same way.
Do i have a better option to solve it, but manually write the position/size of each window in Preferences? Is there any convinient way to store the order of columns in JTable? May be some framework? Just don't want to write boilerplate.
Serialization of the whole big app is unfortunately not an option.
No, there isn't. Don't forget to write the bounds (position/size) of the main JFrame.
And after restoring window position don't forget to check if the position is really in displayed desktop area. The screen configuration may change between application runs (eg. when the user disconnects laptop from a desktop monitor).
Is there a better option than to write the position/size of each window in Preferences?
No, there isn't. Don't forget to write the bounds (position/size) of the main JFrame. You could write the parameters to an XML file instead of a preferences file, but that's an implementation detail.
Is there any convenient way to store the order of columns in a JTable?
Write the column names and positions out to your preferences file.
While this task is common, the implementation of this task is dependent on what you want to save from your GUI.
The way I would save these GUI parameters would be to create a model class that contains all of the bounds and other parameters that you're interested in saving. I would read a XML file that contains these parameters and populate the fields in the model class. If there's no file, I'd set defaults.
The GUI would use the fields in the model class to build the GUI. As the user modifies the GUI, I'd update the model class with the new values.
When the user closes the GUI, I'd write out the model class to an XML file.
I prefer using XML files over properties files because it's easier to see the structure of the model, and I find XML files easier to modify when the GUI changes.
Here's a start. The following code will find the top-most container and save the bounds of all child components to a preferences file which can then be used to restore. This probably won't handle all situations but it works for my app. Future changes can be tracked here.
public class WindowBoundsRestorer
{
private final String filename;
private Properties properties;
public WindowBoundsRestorer( String filename )
{
this.filename = filename;
}
private void setBounds( String key, Component c )
{
key = key + c.getName();
String position = properties.getProperty( key );
if ( c.getName() != null && ! StringUtils.isBlank( position ) )
{
String[] nums = position.split( "," );
c.setBounds( Integer.parseInt( nums[0] ), Integer.parseInt( nums[1] ),
Integer.parseInt( nums[2] ), Integer.parseInt( nums[3] ) );
}
if ( c instanceof Container )
{
key = key + "/";
Container container = (Container) c;
for ( Component child : container.getComponents() )
setBounds( key, child );
}
}
/**
* Loads the properties from the .xml file and sets all named windows with a matching
* name.
*
* #param component Any component in the Swing app. The top-most container will be
* determined from this component.
*/
public void restore( Component component )
{
properties = new Properties();
InputStream is = null;
try
{
is = new FileInputStream( filename );
properties.loadFromXML( is );
}
catch ( IOException e )
{
e.printStackTrace();
return;
}
finally
{
IOUtils.closeQuietly( is );
}
Component top = component;
while ( top.getParent() != null )
top = top.getParent();
setBounds( "", top );
}
private void getBounds( String key, Component c )
{
key = key + c.getName();
String position = String.format( "%d,%d,%d,%d", c.getX(), c.getY(), c.getWidth(), c.getHeight() );
properties.setProperty( key, position );
if ( c instanceof Container )
{
key = key + "/";
Container container = (Container) c;
for ( Component child : container.getComponents() )
getBounds( key, child );
}
}
public void save( Component component )
{
Component top = component;
while ( top.getParent() != null )
top = top.getParent();
properties = new Properties();
getBounds( "", top );
OutputStream os = null;
try
{
os = new FileOutputStream( filename );
properties.storeToXML( os, "Browser" );
}
catch ( IOException e )
{
e.printStackTrace();
}
finally
{
IOUtils.closeQuietly( os );
}
}
}
Whatever you want to remember on the next invocation (window position, etc.) write to a file, and read that file from start up. It's going to need to be persisted to disk, nobody knows what you really want saved (probably not the time sensitive data), and any "automatic" solution can't work unless it also saves the time-sensitive data.
Would you want your application to restore with a record displayed that had been deleted? Probably not.
I've always used java.util.Preferences for this, but a javax.jnlp.PersistenceService works "even for applications that are running in the restricted execution environment."
Related
I am unable to populate a JavaFX TableView object with my own data. I have attempted to modify the code found here to suit the needs of my program.
I added the table used in that tutorial, and it displays properly. I copied that code to create a second table, but cannot get my data to display in that second table.
I believe that I have properly modified the code to accept data from my SNMPInterface class. I attempt to populate my table with static data, and later with data read in from a file. Neither process works, though either will create the columns with the proper headers.
My full project can be found on GitHub.
Initially, I create a TableView object of 'SNMPInterface' class objects:
private TableView< SNMPInterface > interfaceTableView = new TableView<>();
I then create an ObservableList of SNMPInterface objects:
private final ObservableList< SNMPInterface > interfaceData =
FXCollections.observableArrayList(
new SNMPInterface( "99", "testlo" ),
new SNMPInterface( "98", "testeth1" ),
new SNMPInterface( "97", "testeth2" ),
new SNMPInterface( "96", "testbond0" )
);
Later, I create a column for the 'ifIndex' data member:
TableColumn< SNMPInterface, String > ifIndexCol = new TableColumn<>( "Index" );
ifIndexCol.setCellValueFactory( new PropertyValueFactory<>( "ifIndex" ) );
...and the second column for 'ifDescr':
TableColumn ifDescrCol = new TableColumn( "Description" );
ifDescrCol.setCellValueFactory( new PropertyValueFactory<>( "ifDescr" ) );
I then try to add it to the GridPane (named rootNode):
interfaceTableView.setItems( interfaceData );
interfaceTableView.getColumns().setAll( ifIndexCol, ifDescrCol );
rootNode.add( interfaceTableView, 0, 7, 2, 1 );
...but that does not work.
I have a loop to verify that the data is available to the method, and a second that verifies that the data is properly read in from the files. Both containers seem to have valid data, but neither makes it into my table.
My table seems to be effectively the same as the tutorial table, but obviously I am making an error somewhere. Does anyone see where my error is?
The getters and setters on the SNMPInterface class that you use for input to PropertyValueFactory should be marked public, not no modifier (otherwise the reflection logic inherent in the PropertyValueFactory won't find them).
public static class SNMPInterface {
private final SimpleStringProperty ifIndex;
private final SimpleStringProperty ifDescr;
SNMPInterface( String ifIndex, String ifDescr ) {
this.ifIndex = new SimpleStringProperty( ifIndex );
this.ifDescr = new SimpleStringProperty( ifDescr );
}
public String getIfIndex() {
return ifIndex.get();
}
public void setIfIndex( String index ) {
ifIndex.set( index );
}
public String getIfDescr() {
return ifDescr.get();
}
public void setIfDescr( String descr ) {
ifDescr.set( descr );
}
}
Printscreen additional fields useradmin
How can I add some new User Properties to the CQ Users?
I found an solution but it don't work --> http://experience-aem.blogspot.ch/2014/01/aem-cq-56-extend-useradmin-add-new-user.html
I tried to manipulate in CRX the UserProperties.js with new Properties, I see them in useradmin but if I try to add the new propertie in Java Code (not via useradmin) I can save it without error, but the value is empty in useradmin.
And if I try to add some value via useradmin for the new propertie, all user gets the same value.
How can I add new User Properties, that I can set the Value via Java code like the standard properties.
user = userManager.createUser(username, password);
ValueFactory valueFactory = session.getValueFactory();
emailValue = valueFactory.createValue(email);
givennameValue = valueFactory.createValue(givenname);
nameValue = valueFactory.createValue(name);
//User class just accepts Value Object
user.setProperty("profile/" + UserProperties.EMAIL, emailValue);
user.setProperty("profile/" + UserProperties.FAMILY_NAME, nameValue);
user.setProperty("profile/" + UserProperties.GIVEN_NAME, givennameValue);
I found an solution.
Go to crx /libs/cq/security/widgets/source/widgets/security/UserProperties.js
add the fields you need in the items array of the user (Caution - there are items for user and items for groups in the same place)
in the loadRecord method of your JS, you have to add each new field to the "record" object
"items":[{
"xtype":"textfield",
"fieldLabel":CQ.I18n.getMessage("Mail"),
"anchor":"100%",
"vtype":"email",
"msgTarget":"under",
"name":"email"
},{
"xtype":"textfield",
"fieldLabel":CQ.I18n.getMessage("My Field"),
"anchor":"100%",
"msgTarget":"under",
"name":"myfield"
},{
"xtype":"textarea",
"fieldLabel":CQ.I18n.getMessage("About"),
"anchor":"100% -155",
"name":"aboutMe"
}],
loadRecord: function(rec) {
this.enableUserSaveButton(false);
this.enableGroupSaveButton(false);
var type = rec.get("type");
if (type=="user") {
this.activeForm = this.userForm;
this.hiddenForm = this.groupForm;
if (rec.id==CQ.security.UserProperties.ADMIN_ID) {
this.pwdButtons.each(function(bt) {bt.hide(); return true;} )
} else {
this.pwdButtons.each(function(bt) {bt.show(); return true;} )
}
} else {
this.activeForm = this.groupForm;
this.hiddenForm = this.userForm;
}
//is loading additional property from json and show it in formular
rec.data["myfield"] = rec.json["myfield"];
this.activeForm.getForm().loadRecord(rec);
In the java code you can then add the new properties via the "user" object to the new properties. Note that the properties are put into the subfolder "profile".
user.setProperty("profile/" + "myfield", myFieldValue);
Did you try the second approach, posted by "pedro" in the link you've posted?
It probably has to do with pushing the new field to the record:
http://experience-aem.blogspot.com/2014/01/aem-cq-56-extend-useradmin-add-new-user.html?showComment=1390804750445#c2823498719990547675
i hope this may helps you the file exist on http://[host name]:[port]/crx/de/index.jsp#/libs/cq/security/widgets/source/widgets/security/UserProperties.js
and you will have two major properties the first one is for the user this.userForm the other one is this.groupForm for groups.
First of all, I'm not sure about if the title or the tags are correct. If not, someone please correct me
My question is if there are any tools or ways to create an autocomplete list with items from an external source, having netbeans parsing it and warn me if there are any errors.
-- The problem: I use JDBC and I want to model somehow all my schemas, tables and columns so that netbeans can parse it and warn me if I have anything wrong. For example with a normal use of JDBC I would had a function:
ResultSet execSelect( String cols, String table ){
return statement.executeQuery("SELECT "+cols+" FROM "+table); }
The problem is that someone should know exactly what are the available params for that to pass the correct strings.
I would like netbeans to show me somehow an autocomplete list with all available options.
PS. I had exactly the same problem when I was building a web application and I wanted somehow to get all paths for my external resources like images, .js files, .css files etc.
-- Thoughts so far:
My thoughts till now were to put a .java file with public static final String vars with some how nested static classes so that I could access from anywhere. For example:
DatabaseModel.MySchema.TableName1.ColumnName2
would be a String varialble with the 'ColumnName2' column and 'TableName1' table. That would help me with autocompletes but the problem is that there is no type checking. In other words someone could use any string, global defined or not as a table and as a column which is not correct either. I'm thinking to use nested enums somehow to cover these cases about type checking but I'm not sure if that would be a good solution in any case.
Any thoughts?
Finally I came up with writting a "script" that connects to mysql gets all meta data (every column of every table of every schema) and creates a java file with predefined classes and Strings that describes the model. For example:
- If you want the name of the column C1 from table T1 from schema S1 you would type DatabaseModel.S1.T1.C1._ which is a public static final String with the column name.
- If you want the table T2 from schema S2 you would type DatabaseModel.S2.T2 which is a class that implements DatabaseTable interface. So the function: execSelect could take a DatabaseTable and a DatabaseColumn as a parameter.
Here is the code (not tested but the idea is clear I think).
public static void generateMysqlModel(String outputFile) throws IOException, SQLException{
//** Gather the database model
// Maps a schema -> table -> column
HashMap<String,HashMap<String,ArrayList<String>>> model =
new HashMap<String,HashMap<String,ArrayList<String>>>();
openDatabase();
Connection sqlConn = DriverManager.getConnection(url, username, password);
DatabaseMetaData md = sqlConn.getMetaData();
ResultSet schemas = md.getSchemas(); // Get schemas
while( schemas.next() ){ // For every schema
String schemaName = schemas.getString(1);
model.put( schemaName, new HashMap<String,ArrayList<String>>() );
ResultSet tables = md.getTables(null, null, "%", null); // Get tables
while (tables.next()) { // For every table
String tableName = tables.getString(3);
model.get(schemaName).put( tableName, new ArrayList<String>() );
// Get columns for table
Statement s = sqlConn.createStatement(); // Get columns
s.execute("show columns in "+tables.getString(3)+";");
ResultSet columns = s.getResultSet();
while( columns.next() ){ // For every column
String columnName = columns.getString(1);
model.get(schemaName).get(tableName).add( columnName );
}
}
}
closeDatabase();
//** Create the java file from the collected model
new File(outputFile).createNewFile();
BufferedWriter bw = new BufferedWriter( new FileWriter(outputFile) ) ;
bw.append( "public class DatabaseModel{\n" );
bw.append( "\tpublic interface DatabaseSchema{};\n" );
bw.append( "\tpublic interface DatabaseTable{};\n" );
bw.append( "\tpublic interface DatabaseColumn{};\n\n" );
for( String schema : model.keySet() ){
HashMap<String,ArrayList<String>> schemaTables = model.get(schema);
bw.append( "\tpublic static final class "+schema+" implements DatabaseSchema{\n" );
//bw.append( "\t\tpublic static final String _ = \""+schema+"\";\n" );
for( String table : schemaTables.keySet() ){
System.out.println(table);
ArrayList<String> tableColumns = schemaTables.get(table);
bw.append( "\t\tpublic static final class "+table+" implements DatabaseTable{\n" );
//bw.append( "\t\t\tpublic static final String _ = \""+table+"\";\n" );
for( String column : tableColumns ){
System.out.println("\t"+column);
bw.append( "\t\t\tpublic static final class "+column+" implements DatabaseColumn{"
+ " public static final String _ = \""+column+"\";\n"
+ "}\n" );
}
bw.append( "\t\t\tpublic static String val(){ return this.toString(); }" );
bw.append( "\t\t}\n" );
}
bw.append( "\t\tpublic static String val(){ return this.toString(); }" );
bw.append( "\t}\n" );
}
bw.append( "}\n" );
bw.close();
}
PS. For the resources case in a web application I guess someone could get all files recursively from the "resources" folder and fill in the model variable. That will create a java file with the file paths. The interfaces in that case could be the file types or any other "file view" you want.
I also thought that it would be useful to create the .java file from an XML file for any case, so anyone would just create some kind of defintion in an xml file for that purpose.
If someone implements anything like that can post it here.
Any comments/improvements will be welcomed.
I want to insert data in my ontology using this code:
Resource resource = model.createResource(X_NAMESPACE + Global_ID);
Property prop = model.createProperty(RDF_NAMESPACE + "type");
Resource obj = model.createResource(X_NAMESPACE + "X");
model.add(resource, prop, obj);
First, does this code correctly create an individual of the specified type?
When I run this code, it saves without a problem, and the model looks correct, but when I want to query the model, I had problems. For example, I save some data in X, and when I retrieve it, all other data is retrieved.
Your code for creating a resource is correct, but it's not very idiomatic. There are methods provided by the Model interface that will make creating resources easier, and there are methods in the Resource interface that will make adding types easier too. Heres' code that illustrates these:
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;
public class CreateResourceExample {
public static void main(String[] args) {
Model model = ModelFactory.createDefaultModel();
String NS = "http://stackoverflow.com/q/22471651/1281433/";
model.setNsPrefix( "", NS );
// Create the class resource
Resource thing = model.createResource( NS+"ThingA" );
// The model API provides methods for creating resources
// of specified types.
Resource x = model.createResource( NS+"X", thing );
// If you want to create the triples manually, you can
// use the predefined vocabulary classes.
Resource y = model.createResource( NS+"Y" );
model.add( y, RDF.type, thing );
// You can also use the Resource API to add properties
Resource z = model.createResource( NS+"Z" );
z.addProperty( RDF.type, thing );
// Show the model
model.write( System.out, "TTL" );
}
}
How can I delete the saved content in eclipse secure storage programmatically? I need to reset all setting before I run some SWTBot tests.
I know, that I can delete the folder, but isn't there another way?
../.eclipse/org.eclipse.equinox.security
EDIT:
Thanks to Kris I solved the problem.
//part 1
try {
AuthPlugin.getDefault().stop(null);
} catch (final Exception e) {
e.printStackTrace();
}
//part 2
final ISecurePreferences rootNode = SecurePreferencesFactory.getDefault()
.node(ROOT_NODE_NAME);
final String[] names = rootNode.childrenNames().clone();
for (int i = 0; i < names.length; i++) {
rootNode.node(names[i]).removeNode();
}
The problem is solved in part 2. I want to also show a way how to stop the authentication for the secure storage, because it is very annoying, by testing with SWTBot.
You can remove stored values in secure store by using ISecurePreferences. Have a look here
ISecurePreferences root = org.eclipse.equinox.security.storage.SecurePreferencesFactory.getDefault();
if (root == null)
return null;
ISecurePreferences node = root.node("/your.class.path.or.something.else"); // get the node for your application e.g. this.getClass().getCanonicalName()
node = node.node( "some name"); // get custom node from the tree
node.get( "key" ); // load
node.put("key","value", true / false (encrypt) ); // store (no save operation)
node.remove("key"); // remove
node.flush(); // save