JavaFX - How to change default date of DatePicker when clicking Calendar Icon? - javafx

I'm using JFXDatePicker extends DatePicker and want to change default date when clicking Calendar Icon.
The default is the current date and I want to change it to a specific date
by code (It will save a little time when choosing a date in 195x for
example. I disable the Editable so can't type in textfield) And I
don't want to use .setvalue() because it will display that date when
the form was called.
I've used this code but didn't work.
birthday = new JFXDatePicker(LocalDate.of(1980, Month.MARCH, 11));
[http://i228.photobucket.com/albums/ee83/ThamVanTam/JFXDatePicker_zpscdgns2b6.png]

You can simplify #KirantosTera's code by listening to the pickers showingProperty then clearing the editor using Platform.runLater()
JFXDatePicker jfxDatePicker = new JFXDatePicker();
jfxDatePicker.showingProperty().addListener((observableValue, wasFocused, isNowFocus) -> {
if (isNowFocus && jfxDatePicker.getValue() == null) {
jfxDatePicker.setValue(LocalDate.now().minusYears(18));
Platform.runLater(()->{
jfxDatePicker.getEditor().clear();
});
}
});

Unfortunately there is no public api to navigate in the popup content. That's supported by an internal class DatePickerContent, which has a method goToDate(LocalDate, boolean). If you are allowed (and daring enough :) to use internals, you can do so in a onShown handler (to make certain that skin's onShowing listener doesn't interfere):
datePicker.setOnShown(e -> {
if (datePicker.getValue() == null && datePicker.getSkin() instanceof DatePickerSkin) {
DatePickerSkin skin = (DatePickerSkin) datePicker.getSkin();
DatePickerContent popupContent = (DatePickerContent) skin.getPopupContent();
popupContent.goToDate(LocalDate.now().minusYears(18), true);
}
});
Note that this requires to open com.sun.javafx.scene.control.DatePickerContent

Here is my solution, it's not perfect but still good for my issue:
//Setting datepicker :
birthday.setDayCellFactory(picker -> new DateCell() {
#Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
//Setting date 18 years ago
LocalDate today = LocalDate.ofYearDay(LocalDate.now().getYear() - 18, LocalDate.now().getDayOfYear());
//Disable future date
setDisable(empty || date.compareTo(today) > 0);
}
});
//Setting actual value
birthday.setValue(LocalDate.ofYearDay(LocalDate.now().getYear() - 18, LocalDate.now().getDayOfYear()));
//Cover the value by text
String pattern = "dd-MM-yyyy";
formatCalender.format(pattern, birthday);
birthday.getEditor().setText("Date Of Birth");
birthday.setPromptText(null);

Related

How to display (the hours of) a local time in a spinner in 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);

Creating a button with a dialog in AX 2012

I want to make a Button.
I have a EDT "Resigning", which can't be edited, it only can be edited once and that when I press the button.
When clicking the button a Dialog shall Pop up where I can type in the date.
I have to write a class I think, but I am struggling a lot...
With Kind Regards
Khashayar
you can write the code in clicked method of the button.
Here a simple job to do that:
static void StackOverflow(Args _args)
{
Dialog dialog;
DialogField dialogDate;
date newDate;
;
dialog = new Dialog("Set new date");
dialogDate = dialog.addField(ExtendedTypeStr("YourEDTName"), "New date:");
if (dialog.run())
{
newDate = dialogDate.value(); //Get value of new date.
//Here code to update your table
}
}
To prevent from overwriting existing value you can modify your method as following:
public void clicked()
{
Dialog dialog;
DialogField dialogDate;
date newDate;
;
if (EmploymentTable.Resigning == dateNull())
{
dialog = new Dialog("Set new date");
dialogDate = dialog.addField(ExtendedTypeStr("YourEDTName"), "New date:");
if (dialog.run())
{
newDate = dialogDate.value(); //Get value of new date.
//Here code to update your table
}
}
else
{
warning("Value already exists.");
}
}
The code above is checking whether value already exists, before allowing to assign new value.
More better approach is disabling the button if value already exists. To do this write a method to disable/enable your button and call it in active method on form datasource.

How to show/open JavaFX DatePicker editor to a specific calendar date without setting any value in its textbox?

I wish to enable date picking for a time range Jan 2000 - Dec 2014 and have disabled dates outside this range and want to open the DatePicker editor to a date within this range without setting value(setValue() or Constructor) to it, since I want the text box empty. Can this be done?
You can set date you need by constructor or setValue and clear textbox with picker.getEditor().clear().
To disable dates from outside you can set custom DateCellFactory:
LocalDate minDate = LocalDate.of(2000, Month.JANUARY, 1);
LocalDate maxDate = LocalDate.of(2014, Month.DECEMBER, 31);
DatePicker picker = new DatePicker(minDate.plusYears(2));
picker.setDayCellFactory((p) -> new DateCell() {
#Override
public void updateItem(LocalDate ld, boolean bln) {
super.updateItem(ld, bln);
setDisable(ld.isBefore(minDate) || ld.isAfter(maxDate));
}
});
Platform.runLater(() -> {
picker.getEditor().clear();
});

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.

Get old text from change event?

Can I somehow find out what was the change in the textfield? I would want to compare the old text with the new text ... the problem is, that I have multiple textAreas in a tab-editor, and all the textAreas are watched by one eventListener. I want to get a value calculated by the next formula:
globalChangeCount += thisTextArea.currentCharacterCount - thisTextArea.oldtCharacterCount
where the globalChangeCount is a value modified by all changes in any of the textAreas.
I am searching for these values through the event variable, but can't seam to find the old text of the textArea.
This may or may not be what you're looking to do:
package
{
import mx.controls.TextArea;
public class CountingTextArea extends TextArea
{
public var staleText : String = "";
[Bindable("textChanged")]
[NonCommittingChangeEvent("change")]
public function get charDiff() : int
{
var diff : int = staleText.length - text.length;
staleText = text;
return diff;
}
public function CountingTextArea()
{
super();
}
}
}
I made it so that you can use it as a source for binding. Instead of subscribing to the event on each TextArea, you can use:
function addWatchers():void
{
ChangeWatcher.watch(countingTextArea1, ["charDiff"], charDiffChangeHandler );
...
ChangeWatcher.watch(countingTextArea5, ["charDiff"], charDiffChangeHandler );
}
With the event handler somewhere too:
function charDiffChangeHandler( event : PropertyChangeEvent ) : void
{
trace(event.currentTarget.charDiff);
// or
trace(event.newValue);
}
You can use event.currentTarget to get a reference to the TextArea that fired the event, and use the focusIn event to execute a function to populate a variable with the old text value.
Maybe you should just subclass the TextArea and create an oldText field variable you update internally after all the external listeners have been notified.

Resources