Java UIManager key list - java

I've seen people use UIManager to change strings of some pre-created swing components (e.g. JFileChooser).
Where can I find some kind of reference that will tell me which strings in which components are changeable, and how can I access them?
To clarify:
I know that UIManager.put(key, newString); will change text of string that key references to, to "newString".
Where can I find the list of keys?

Keys for UIManager are Look and Feels sensitive, means (for example) value Keys for Metal Look and Feel could be diferrent when you comparing value from System Look and Feel, notice or Key missed too
use UIManager Defaults by #camickr

You're probably best of by dumping the list yourself using code like the following since keys might differ:
public static void printUIManagerKeys()
{
UIDefaults defaults = UIManager.getDefaults();
Enumeration<Object> keysEnumeration = defaults.keys();
ArrayList<Object> keysList = Collections.list(keysEnumeration);
for (Object key : keysList)
{
System.out.println(key);
}
}
For me the list contains 1365 elements on Windows 10.

These keys are provided by Swing PLAF resource bundles, and you can find them in the JDK sources. See e.g.:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/com/sun/swing/internal/plaf/basic/resources/basic.java
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/com/sun/java/swing/plaf/windows/resources/windows.java
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/com/sun/java/swing/plaf/gtk/resources/gtk.java
...
String values for languages other than English are provided by adjacent bundle files.
And you can add one more bundle to any of these families just by creating one more file for desired human language and placing it anywhere on your classpath. Bundles in .java and .properties format work equally well, though .java format may be slightly more Unicode-friendly...
It may be good to keep in mind though that direct adding of content to com.sun package may violate the Java license. So to be on the safe side, it may be wise to move your extra resources to a package of your own and register it with UIManager like this:
UIManager.getDefaults().addResourceBundle("mypackage.swing.plaf.basic.resources.basic");

Seems like one has to run some code to see all the keys. I know the question is for java, but really the quickest way to obtain the keys is to launch groovy (or gradle) script:
javax.swing.UIManager.getDefaults().keys().toList().toSorted().each {println it}
Paste it to a file and call groovy keys.groovy or gradle -b keys.groovy, whatever tool is easier for you to get.
Without creating a file it's also doable with groovy. Simply execute:
groovy -e "javax.swing.UIManager.getDefaults().keys().toList().toSorted().each {println it}"

Related

How to make a JFileChooser with a different language?

I want to know how I can make a JFileChooser in the Swedish language.
Unfortunately it turns out that if I could use a JDK version 10 or earlier i could actually do this by creating a Locale object and make it the default.
But we are discouraged to use this old version for any new programs.
But from JDK version 11 and forward choosing Swedish Locale no longer works.
So I have seen that people have been able to change individual strings for the FileChooser like in this example:
https://coderanch.com/t/475470/java/customizing-JFIleChooser
But this feels unsatisfactory to me.
At least for as long as I do not know how I can learn about how I can find those Strings and where they are located.
Maybe I will run into the same problem again with some other GUI component and then I still don't know what to do.
This works with JDK v. 10 or earlier:
//This is in my Main:
Locale sverje = new Locale("sv", "SE"); //Creates a instance of Locale for Swedish, Sweden.
Locale.setDefault(sverje); //Sets this to default.
//Then I call a class that opens a Frame and handles the FileChooser.
This is an example of modifying an individual string:
UIManager.put("FileChooser.cancelButtonText", "Cancelar"); //Changing cancel button text to Portugese
If I need to use this method it would be nice to know how to find the strings like I said before.
It would also be nice to know what is going on when you "put" in the new String value like in the example.
I believe that the JFileChooser somehow inherits the Strings in several steps, and that is what allows us to write "FileChooser.cancelButtonText" even if there actually is no "cancelButtonText" in the FileChooser class, rather (I'm guessing!) it inherits it from a so called ResourceBundle and then from there to the Localeclass and from there to some other class or classes before the FileChooser uses it.
So is this a correct assumption and how can you trace the Key / name / location of those strings from the FileChooser class to where the actually are?
Is it the ResourceBundle or the FileChooser or some other part that was changed since it stopped working from version 11?
Can / should I try to make changes to the ResourceBundle to fix this in the most professional way?
You can find the full list (including FileChooser keys) in the first answer of this post: List of Java Swing UI properties?
I think it will be enough setting only the properties ending in "Text".
AFAIK UIManager.put is just updating UIDefaults (the map that contains all the default names) so, as long as there is just one language available in the application, there is no need to use a ResourceBundle.
So correct me if I am wrong.
But I think the answer is something like this:
If you want to use one of the languages that is supported for the Swing Component just set the correct Locale and you are done.
If not it seems like using UIManager.put is the best way to go.
I was hoping to find a resource bundle containing all of the text strings but now I do no longer think that such a thing exists.
So my understanding at the moment is this:
The JComponents such as the FileChooser are generalized Components that are meant to work on many different platforms and operative systems.
And they use classes called "Look & Feel" to get their final form depending on the intended Platform.
This is where the UIManager comes in.
It allows you to decide what "Look & Feel" you want to use.
So in my case it will use a look and feel called:
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel".
You can get this information using:
System.out.println(UIManager.getSystemLookAndFeelClassName());
And I believe that the UIManager will create classes called UIDefaults using some algorithm.
The UIDefaults will contain the values that gives the JComponents their "Look & Feel" i.e. their appearance & behaviour.
But the UIDefaults classes are not pre-existing.
They are created based on setup.
However I believe that they will get some of their data from a resource file that is not truly a ResourceBundle but at least extends the ResourceBundle class.
But this still does not contain all the necessary Strings to fully customize the FileChooser.
This link shows an example of these resource files that are specific to the Windows version (L&F) of the FileChooser:
https://code.yawk.at/java/6/com/sun/java/swing/plaf/windows/resources/
So the data is apparently split up and it does not come from a single source.
It is collected from different sources and put into the UIDefaults class that works like a Database for the values.
To sum it all up.
The best way to go might be to create a class that has a method to put all the String values into the UIDefaults using the UIManager.
And I suppose you could prepare for internationalization by letting this method get it's strings from a resource bundle that you have created yourself.
The best list of Keys seems to be this one:
https://thebadprogrammer.com/swing-uimanager-keys/
But unfortunately although seemingly exhausting there is still information missing.
To fully customize all the Strings in the FileChooser in addition to the Keys you will find in this list you will also need to change the value of this Key:
"saveInLabelText".
So these are all the String I changed and I believe they will customize most of the Strings for the Windows version of the FileChooser:
//Strings for Open file-dialogue: ***************************************************************************
//The numbers in the comments refers to the order of appearance of the Stirng values in the Frame
UIManager.put("FileChooser.openDialogTitleText","Open"); //1.
UIManager.put("FileChooser.lookInLabelText","Look in:"); //2.
UIManager.put("FileChooser.fileNameLabelText","File name:"); //3.
UIManager.put("FileChooser.filesOfTypeLabelText","Files of type:"); //4.
UIManager.put("FileChooser.openButtonText","Open"); //5.
UIManager.put("FileChooser.cancelButtonText", "Cancel"); //6.
UIManager.put("FileChooser.acceptAllFileFilterText","All Files"); //7.
//End of Open file-dialogue ***************************************************************************
//Strings for Save file-dialogue ***************************************************************************
UIManager.put("FileChooser.saveDialogTitleText","Save as"); //1.
UIManager.put("FileChooser.saveInLabelText","Save in:"); //2. This was not in the list but works!
// The strings with number 3 & 4 are the same as the ones for the Open file-dialogue so you do not need to set them here.
UIManager.put("FileChooser.saveButtonText","Save"); //5.

Non-localized strings in android

How do I avoid (some) of my string resources getting localized?
Sometimes I need the same string multiple places. For instance when defining a preference I need the preference key both in my preferences.xml and in my java code in order to get the preference value. Either I can manually define the key twice (which I do now) but I feel that my list of keys is getting large and error prone.
I could also define the key in my strins.xml but then I fear it will get translated (sooner or later (by mistake?)). I fear this could cause problems to have the same preference value store multiple times with different keys. What if the user changes language and all the settings got reset?
Is there a way to define a string - accessible both in code and xml - which will not get translated as a part of the localization process?
In general, if you provide the string only in your default strings.xml it will appear the same on all locales. In addition you can use the "translatable" attribute which will tell Lint that this string is not designed to be translated, and will serve for documentation purposes.
Just use translatable=false. And I suggest putting your preferences keys to separate resource file as it would be easier to manage.
<string name="Key" translatable="false">my key</string>

Best approach for automatically generating I18N key strings in Java

I've taken a look at the following post to grasp a basic idea of how to deal with I18N:
Where to place i18n key strings in Java
But more than that, I have an intention of automatically generating a Java class with constants storing key strings of I18n property files. I know it could be feasibly done using Java itself, however, I wonder which is the best approach (using Ant, Batch or something else...)?
The best approach is to give the identifiers yourself.
The ID can give hint to the translator what the string is about.
In fact, some consistency in naming convention is best:
dialog.print.title = Print
menu.file.print = Print
The two entries have to be translated differently in some languages (for instance in French it would be "Imprimer" for a button and "Impression" for a label / title).
Think it it this way: would you like to maintain some code where all variable names are machine generated?

Is there a way to search the variables available at the current place in the stack during remote debugging?

I'm remote debugging a Java application and (not for the first time) I find myself looking for a value without knowing what variable might hold it (if any at all). This is especially hard to find since I'm stepping through library code rather than my own code, so I was wondering; since eclipse can display the variables currently available on the stack, along with all contained values, is there any way I can search these? Or at the very least dump it out as text somewhere and grep it or something.
I usually do an export to JSON using Jackson's ObjectMapper whenever I find myself into the situation of having to search among a bunch of values caught while debugging. On breakpoint hit, let's say I want to search some string inside a text representation of myObj, which could be some messy POJO deep with nested objects. Just evaluate the following:
org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();
mapper.writeValue(new java.io.File("/tmp/myObj.json"), myObj);
and then go grep your value inside the file you just created.
YMMV: if you have no idea where to start the search you'll have to iterate through what's available on the stack. Also the JSON representation might not be suitable for every kind of search.
I'm not sure about the feature you are asking for but there is another approach you could take. Assuming you know the general area AND the object you are looking for isn't too common, eclipse supports conditional breakpoints so you could set breakpoints on the end of methods chechking the method variables and object state.
You could try evars. I haven't tried the search function, but it allows expanding and exporting all the variables on the stack to a file, which you can then grep for your value. I installed the latest version into Eclipse manually, i.e. putting the jar in the dropins/plugins directory. Worked for me on Eclipse 3.6.1.

Barring copy & paste, is there a way to share Java detail formatters

We have 5-10 developers working on Eclipse with Java here in our shop, and we often are debugging classes that don't have debug-friendly toString().
Along comes Detail Formatters to save the day. Hurray! But only my day. If I want to share the joy with my fellow devs, I THINK I have to do some copying and pasting, as do they.
That sucks. We've got N different version control systems that work in Eclipse... it seems like this would be something that folks would Like To Pass Around.
Nothing in the file->export... dialog. Nothing via searching the online help. Nothing.
I managed to track at least some of the settings to /workspace/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.dbug.ui.prefs, but Have Reason To Believe there's more to it than that. Plus, the thought of putting something burried deep in a hidden folder into source control puts my teeth on edge.
Is there a better way to share detail formatters? Ideally this would be something we could just check into our code repo and disseminate that way.
EDIT: I'm using Helios, Service Release 1, build id 20100917-0705.
In addition to the javaLogicalStructures extension point (for adding logical structure to given classes), there's also one called detailPaneFactories. But this is for creating the pane the text (or whatever, thanks to this extension point) the detail formatter renders to. Neither allows extenders to list existing detail formatters (or logical structures for that matter).
The bottom of the detailPaneFactories extension does have Something Interesting To Say:
Supplied Implementation:
The debug platform contributes a detail pane factory providing a default
text source viewer detail pane. The default detail pane displays textual
details of a selected element based on the corresponding debug model
presentation's implementation of computeDetail(IValue value,
IValueDetailListener listener).
computeDetail sounds promising. I'll keep ya posted (unless someone else beats me to it... hurray bounties).
Hmm... org.eclipse.jdt.debug.ui.JavaDebugUtils.getPreferenceStore() sounds promising, but I'd still rather not write a plugin for this myself.
Ah... well. Here's the code org.eclipse.jdt.internal.debug.ui.JavaDetailFormattersManager uses to load them:
/**
* Populate the detail formatters map with data from preferences.
*/
private void populateDetailFormattersMap() {
String[] detailFormattersList= JavaDebugOptionsManager.parseList(JDIDebugUIPlugin.getDefault().getPreferenceStore().getString(IJDIPreferencesConstants.PREF_DETAIL_FORMATTERS_LIST));
fDetailFormattersMap= new HashMap(detailFormattersList.length / 3);
for (int i= 0, length= detailFormattersList.length; i < length;) {
String typeName= detailFormattersList[i++];
String snippet= detailFormattersList[i++].replace('\u0000', ',');
boolean enabled= ! JavaDetailFormattersPreferencePage.DETAIL_FORMATTER_IS_DISABLED.equals(detailFormattersList[i++]);
fDetailFormattersMap.put(typeName, new DetailFormatter(typeName, snippet, enabled));
}
}
So the string in the preference store is just a bunch of CSVs with type-name,snippet,enabled,type-name... replace \u0000 with , in the snippets, and you're good to go.
That handles the export (hell, you could just dump the preference string whole hog).
Import wouldn't be much harder, though it'd be nice to not overwrite existing types, or given the user the option to do so, perhaps even with a diff of the two snippets in question.
OTOH, I'd really rather not rely on the inner workings of a class in *.internal.*.
From the Eclipse 3.8 and 4.2 M5 - New and Noteworthy:
Detail formatters can now be exported as separate preferences.
Previously the only way to share detail formatters was to export all of your workspace settings.
This closes the bug 224815 mentioned by Brian De Alwis in his answer:
"Make Detail formatters exportable" (with that patch)
Although there is nothing explicit in the preferences export wizard, exporting everything will also write the detail formatters. Just search in the output file for /instance/org.eclipse.jdt.debug.ui/org.eclipse.jdt.debug.ui.detail_formatters and share only those lines.
Update: There seems to be a bug in the importer, you have to remove the /instance/ prefix from each line before importing the file.
Alternatively, as they are stored in a properties file in the workspace metadata, you can share that (although you'll probably overwrite other debug settings if you just copy the file):
${workspace}\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.jdt.debug.ui.prefs
Using a "macro" might do the trick here.
You will have to
Install a plugin that lets you
record Macros
Start recording Macro and configure Detail formatters using Eclipse Menus
Save and keep that
macro on some shared directory
Install that plugin and run macro on
PCs used by other developers
One such plugin is : http://sourceforge.net/projects/practicalmacro/reviews/
This issue was filed in the Eclipse Bugzilla as bug 224815. The problem is that the detail formatters were overlooked when configuring the import/export preference transfers. The fix, providing it's accepted, should be in the 3.8/4.2 M6 due out at the end of January.

Categories

Resources