How to display (the hours of) a local time in a spinner in JavaFx - javafx

How do I set the value of SpinnerValueFactory<LocalTime> valueFactory = new SpinnerValueFactory<LocalTime>() in a spinner?
Attempting to set and display the value in the spinner editor with hrsSpinner.getValueFactory().setValue(valueFactory); , Java tells me:
The method setValue(LocalTime) in the type SpinnerValueFactory<LocalTime> is not applicable for the arguments (SpinnerValueFactory<LocalTime>).
Another approach I've tried is hrsSpinner.setValueFactory(valueFactory);. I get no errors. But the hours are initially not displayed in the spinner editor until I've clicked on the spinner to increment or decrement the hours.
Any ideas how I can solve my problem? Here is a sample of my code I'm using
Calendar calendar = new GregorianCalendar();
int hour;
this.hour = calendar.get(Calendar.HOUR_OF_DAY);
if(hourRadioButton.isSelected() == true)
{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh");
ObservableList<String> hours = FXCollections.observableArrayList(String.valueOf(hour));
SpinnerValueFactory<LocalTime> valueFactory = new SpinnerValueFactory<LocalTime>() {
{
setConverter(new LocalTimeStringConverter(formatter,null));
}
#Override
public void decrement(int steps) {
if(getValue() == null)
{
setValue(LocalTime.now());
}
else
{
LocalTime localTime = (LocalTime) getValue();
setValue(localTime.minusHours(1));
}
}
#Override
public void increment(int steps) {
if (this.getValue() == null)
{
setValue(LocalTime.now());
}
else
{
LocalTime localTime = (LocalTime) getValue();
setValue(localTime.plusHours(1));
}
}
};
//hrsSpinner.setValueFactory(valueFactory);
hrsSpinner.getValueFactory().setValue(valueFactory);
}
Thank you very much in advance for your time and help!!!
AvJoe

hrsSpinner.getValueFactory() is an expression of type SpinnerValueFactory<LocalTime>. Using setValue on this is not possible with this parameter and it wouldn't do what you want.
Use the setter for the valueFactory property instead:
hrsSpinner.setValueFactory(valueFactory);
This way of setting the value factory seems to stem from the bad practice of using the setter of the property object instead of using the more concise and thus easier to parse version using the setter corresponding to the property. The version using the property object's setter would be
hrsSpinner.valueFactoryProperty().set(valueFactory);
in this case.
Furthermore I don't recommend mixing Calendar and java.time API. If you've got the choice, go with the java.time api completely. It provides the same functionality and is much easier to use imho. E.g. assuming you wanted to use the calendar to truncate the value to full hours, you could use truncateTo instead:
SpinnerValueFactory<LocalTime> factory = new SpinnerValueFactory<LocalTime>() {
{
setValue(defaultValue());
}
private LocalTime defaultValue() {
return LocalTime.now().truncatedTo(ChronoUnit.HOURS);
}
#Override
public void decrement(int steps) {
LocalTime value = getValue();
setValue(value == null ? defaultValue() : value.minusHours(steps));
}
#Override
public void increment(int steps) {
LocalTime value = getValue();
setValue(value == null ? defaultValue() : value.plusHours(steps));
}
};
Spinner<LocalTime> spinner = new Spinner<>();
spinner.setValueFactory(factory);

Related

JsonConverter and Swashbuckle - Approach for decorating a swagger

I'm playing around and developed a simple custom JsonConverter that takes a min and max temperature and have decorated my model class as follows and validates that the temperature falls in that range.
[JsonConverter(typeof(TemperatureConverter), 5, 10)]
public int Temperature { get; set; }
This is all good but I'm wondering what's the approach to best output the correct decoration in my swagger file generated by swashbuckle... like so:
name: Temperature
schema:
type: integer
minimum: 5
maximum: 10
I know this is a trivial example, but it's more the approach to tying JsonConverter to the generation of the swagger I'm interested in.
I'm currently looking at ISchemaFilter but can't see how I can get the type of converter that decorates the property.
Thanks
You have to be at the parent schema level, looking at it's properties. By the time it gets to the property itself, it is too late, as there is no link back to the parent class.
I was using a custom attribute, not JsonConverter, but something like this should work for detecting the attribute.
public class TemperatureSchemaFilter : ISchemaFilter
{
public void Apply(Schema schema, SchemaFilterContext context)
{
var converterProperties = context.SystemType.GetProperties().Where(
prop => prop.CustomAttributes.Select(
attr => attr.AttributeType == typeof(JsonConverterAttribute)).Any()
).ToList();
foreach (var converterProperty in converterProperties)
{
var converterAttribute = (JsonConverterAttribute)Attribute.GetCustomAttribute(converterProperty.PropertyType, typeof(JsonConverterAttribute));
if (converterAttribute.ConverterType != typeof(TemperatureConverter)) continue;
Schema propertySchema = null;
try
{
propertySchema = schema.Properties.First(x => x.Key.ToLower().Equals(converterProperty.Name.ToLower())).Value;
}
catch (Exception)
{
continue;
}
if (propertySchema == null) continue;
propertySchema.Minimum = (double) converterAttribute.ConverterParameters[0];
propertySchema.Maximum = (double) converterAttribute.ConverterParameters[1];
}
}
}
Unfortunately my environment is currently hosed, so I can't test it out, but I think this is the way to go.

Swashbuckle rename Data Type in Model

I'm putting together a web API that needs to match an external sources XML format and was looking to rename the Data Type objects in the swagger output.
It's working fine on the members of the class but I was wondering if it was possible to override the class name as well.
Example:
[DataContract(Name="OVERRIDECLASSNAME")]
public class TestItem
{
[DataMember(Name="OVERRIDETHIS")]
public string toOverride {get; set;}
}
In the generated output I end up seeing
Model:
TestItem {
OVERRIDETHIS (string, optional)
}
I'd hope to see
OVERRIDECLASSNAME {
OVERRIDETHIS (string, optional)
}
Is this possible?
Thanks,
I had the same problem and I think I solved it now.
First of all add SchemaId in Swagger Configuration (from version 5.2.2 see https://github.com/domaindrivendev/Swashbuckle/issues/457):
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SchemaId(schemaIdStrategy);
[...]
}
Then add this method:
private static string schemaIdStrategy(Type currentClass)
{
string returnedValue = currentClass.Name;
foreach (var customAttributeData in currentClass.CustomAttributes)
{
if (customAttributeData.AttributeType.Name.ToLower() == "datacontractattribute")
{
foreach (var argument in customAttributeData.NamedArguments)
{
if (argument.MemberName.ToLower() == "name")
{
returnedValue = argument.TypedValue.Value.ToString();
}
}
}
}
return returnedValue;
}
Hope it helps.
Pretty old question, but as I was looking for a similar solution, I bumped into this.
I think the code in Vincent's answer might not work.
Here is my take on it:
private static string schemaIdStrategy(Type currentClass)
{
var dataContractAttribute = currentClass.GetCustomAttribute<DataContractAttribute>();
return dataContractAttribute != null && dataContractAttribute.Name != null ? dataContractAttribute.Name : currentClass.Name;
}
Adding to the thread as I am not able to use the answer with Swashbukle for AspNetCore.
I am doing this. However I am not totally happy as if the object is contain in another object it is showing its original name. For example if you have a result set that is Paged That result is shown incorrectly.So this is not a final answer but might work on simple use cases.
I am using a Schema Filter. And the object just have [JsonObject(Title="CustomName")] as I get the Title property for the data type.
First Define a class like this:
public class CustomNameSchema : ISchemaFilter
{
public void Apply(Schema schema, SchemaFilterContext context)
{
if (schema?.Properties == null)
{
return;
}
var objAttribute = context.SystemType.GetCustomAttribute<JsonObjectAttribute>();
if( objAttribute!= default && objAttribute?.Title?.Length > 0)
{
schema.Title = objAttribute.Title;
}
}
}
On the startup you must configure a SchemaFilter
c.SchemaFilter<CustomNameSchema>();

how to get text from textview using espresso

I want get text string shown in a textview in LinearLayout. can espresso do that? If not, is there other way to do that or can I use android api in espresso test case? I am using API 17 18 or newer, espresso 1.1(It should be the latest one.). I have no clue about this. Thanks.
The basic idea is to use a method with an internal ViewAction that retrieves the text in its perform method. Anonymous classes can only access final fields, so we cannot just let it set a local variable of getText(), but instead an array of String is used to get the string out of the ViewAction.
String getText(final Matcher<View> matcher) {
final String[] stringHolder = { null };
onView(matcher).perform(new ViewAction() {
#Override
public Matcher<View> getConstraints() {
return isAssignableFrom(TextView.class);
}
#Override
public String getDescription() {
return "getting text from a TextView";
}
#Override
public void perform(UiController uiController, View view) {
TextView tv = (TextView)view; //Save, because of check in getConstraints()
stringHolder[0] = tv.getText().toString();
}
});
return stringHolder[0];
}
Note: This kind of view data retrievers should be used with care. If you are constantly finding yourself writing this kind of methods, there is a good chance, you're doing something wrong from the get go. Also don't ever access the View outside of a ViewAssertion or ViewAction, because only there it is made sure, that interaction is safe, as it is run from UI thread, and before execution it is checked, that no other interactions meddle.
If you want to check text value with another text, you can create Matcher. You can see my code to create your own method:
public static Matcher<View> checkConversion(final float value){
return new TypeSafeMatcher<View>() {
#Override
protected boolean matchesSafely(View item) {
if(!(item instanceof TextView)) return false;
float convertedValue = Float.valueOf(((TextView) item).getText().toString());
float delta = Math.abs(convertedValue - value);
return delta < 0.005f;
}
#Override
public void describeTo(Description description) {
description.appendText("Value expected is wrong");
}
};
}

how to update Visual Studio UI when using DynamicItemStart inside a vsix package

I'm implementing a DynamicItemStart button inside a Menu Controller. I'm loading the dynamic items for this button when Visual Studio starts. Everything is loaded correctly so the initialize method is called an I see all the new items in this Dynamic button. After the package is completely loaded I want to add more items to this Dynamic button, but since the package is already loaded the initialize method is not called again and I cannot see the new items in this Dynamic button. I only see the ones that were loaded when VS started.
Is there any way that I can force the update of this Dynamic button so it shows the new items?. I want to be able to update the VS UI after I added more items but outside the Initialize method.
The implementation I did is very similar to the one showed on this msdn example:
http://msdn.microsoft.com/en-us/library/bb166492.aspx
Does anyone know if an Update of the UI can be done by demand?
Any hints are greatly appreciated.
I finally got this working. The main thing is the implementation of a derived class of OleMenuCommand that implements a new constructor with a Predicate. This predicate is used to check if a new command is a match within the DynamicItemStart button.
public class DynamicItemMenuCommand : OleMenuCommand
{
private Predicate<int> matches;
public DynamicItemMenuCommand(CommandID rootId, Predicate<int> matches, EventHandler invokeHandler, EventHandler beforeQueryStatusHandler)
: base(invokeHandler, null, beforeQueryStatusHandler, rootId)
{
if (matches == null)
{
throw new ArgumentNullException("Matches predicate cannot be null.");
}
this.matches = matches;
}
public override bool DynamicItemMatch(int cmdId)
{
if (this.matches(cmdId))
{
this.MatchedCommandId = cmdId;
return true;
}
this.MatchedCommandId = 0;
return false;
}
}
The above class should be used when adding the commands on execution time. Here's the code that creates the commands
public class ListMenu
{
private int _baselistID = (int)PkgCmdIDList.cmdidMRUList;
private List<IVsDataExplorerConnection> _connectionsList;
public ListMenu(ref OleMenuCommandService mcs)
{
InitMRUMenu(ref mcs);
}
internal void InitMRUMenu(ref OleMenuCommandService mcs)
{
if (mcs != null)
{
//_baselistID has the guid value of the DynamicStartItem
CommandID dynamicItemRootId = new CommandID(GuidList.guidIDEToolbarCmdSet, _baselistID);
DynamicItemMenuCommand dynamicMenuCommand = new DynamicItemMenuCommand(dynamicItemRootId, isValidDynamicItem, OnInvokedDynamicItem, OnBeforeQueryStatusDynamicItem);
mcs.AddCommand(dynamicMenuCommand);
}
}
private bool IsValidDynamicItem(int commandId)
{
return ((commandId - _baselistID) < connectionsCount); // here is the place to put the criteria to add a new command to the dynamic button
}
private void OnInvokedDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand invokedCommand = (DynamicItemMenuCommand)sender;
if (null != invokedCommand)
{
.....
}
}
private void OnBeforeQueryStatusDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand matchedCommand = (DynamicItemMenuCommand)sender;
bool isRootItem = (matchedCommand.MatchedCommandId == 0);
matchedCommand.Enabled = true;
matchedCommand.Visible = true;
int indexForDisplay = (isRootItem ? 0 : (matchedCommand.MatchedCommandId - _baselistID));
matchedCommand.Text = "Text for the command";
matchedCommand.MatchedCommandId = 0;
}
}
I had to review a lot of documentation since it was not very clear how the commands can be added on execution time. So I hope this save some time whoever has to implement anything similar.
The missing piece for me was figuring out how to control the addition of new items.
It took me some time to figure out that the matches predicate (the IsValidDynamicItem method in the sample) controls how many items get added - as long as it returns true, the OnBeforeQueryStatusDynamicItem gets invoked and can set the details (Enabled/Visible/Checked/Text etc.) of the match to be added to the menu.

Is this common practice for a read-only property that accesses the database

If I have a read-only property on an object that fills itself via the DB, is this what I should be doing, or is there a better way to make sure it's already been evaluated?
private List<Variable> _selectedVariables;
public new List<Variable> SelectedVariables
{
get
{
if (_selectedVariables == null)
{
_selectedVariables = SomeFunctionThatCallsDB();
}
return _selectedVariables;
}
}
That's fine for a single thread; but you will have problems if that is going to be in a situation where you have multithreaded gets.
EDIT: Threadsafing:
Simple Threadsafe pattern:
private readonly object _objectLock = new object();
private List<T> _someList = null;
public List<T> MyStuff
{
get
{
if(_someList == null)
{
lock(_objectLock)
{
if(_someList == null)
_someList = LoadFromDB();
}
}
return _someList;
}
}
You check to see if set, then lock, then check again to make sure you covered the race condition.

Resources