JavaFX - Get CheckBox properties from outside GUIController - user-interface

In JavaFX I want to check if a checkbox is selected and I want to do this using the lookup(#id) method. However this method returns a Node, which doesn't have the isSelected() method.
The code below shows the GUIController and a class Visualize it calls, where the status of the checkbox is read. I added a solution (reading the checkbox properties in GUIController and passing them to Visualize), but this is not how I want to proceed. I whish that the checkbox status is read in Visualize, because there will be many other GUI elements that I need to read so it is more compact to pass on a single object to Visualize instead of a list precomputed in GUIController.
Thank you for suggestions!
GUI Controller:
public class GUIController implements Initializable {
#FXML private AnchorPane RootPane;
#FXML private CheckBox TextCheckBox;
#Override
public void initialize(URL url, ResourceBundle rb) {
Boolean TextCheckBoxSelected = TextCheckBox.isSelected();
Visualize visualizeInstance = new Visualize();
root3D = visualizeInstance.draw(RootPane, TextCheckBoxSelected);
/* ... */
Class called by GUIController:
public class Visualize {
public Visualize() {
//
}
public Group draw(AnchorPane RootPane, Boolean TextCheckBoxSelected) {
System.out.println(RootPane.lookup("#TextCheckBox"));
System.out.println(TextCheckBoxSelected);
/* ... */
Output:
CheckBox[id=TextCheckBox, styleClass=check-box]'Text'
true

If you really want to do it this way, just downcast the result of the lookup:
public class Visualize {
// ...
public Group draw(AnchorPane rootPane) {
CheckBox textCheckBox = (CheckBox) rootPane.lookup("#TextCheckBox");
boolean selected = textCheckBox.isSelected();
// ...
}
}
If you are doing this because you need your Visualize object to respond to changes in the CheckBox's selected state, then consider passing a BooleanProperty instead, which you can observe if you need:
public class Visualize {
private BooleanProperty selectedProperty ;
public Visualize(BooleanProperty selectedProperty) {
this.selectedProperty = selectedProperty ;
// ...
}
// ...
public Group draw() {
boolean selected = selectedProperty.get();
// ...
}
}
and
Visualize visualizeInstance = new Visualize(textCheckBox.selectedProperty());
root3D = visualizeInstance.draw();

Related

How to validate number only textbox in SmartGWT?

Textbox should accept only numbers, I would like to use anyother Handlers other than ChangedHandler/ Changehandler/ KeyPressHandler
My Validation class,
public class UnderLyingIDChangeHandler implements ChangedHandler {
private final CreditRiskView creditRiskView;
public UnderLyingIDChangeHandler(CreditRiskView creditRiskView) {
this.creditRiskView = creditRiskView;
}
#Override
public void onChanged(ChangedEvent event) {
String value= (String) event.getItem().getValue();
if(!value.matches("[0-9]*")){
creditRiskView.invalidUnderlyingID();
}
}
This is the main class where I need to show the validation
public class CreditRiskView{
private TextItem underlyingIDField;
public void addunderlyingIDInputChangeHadler(ChangedHandler changedHandler) {
//logic is that this method will invoked in the UnderLyingIDChangeHandler class
underlyingIDField.addChangedHandler(changedHandler);
}
public void invalidUnderlyingID(){
// I don't know how to set an error message as underlyingIDField.clearValue()
method is not doing well.
}
}
If the textbox is a TextItem in a DynamicForm it works like this:
IsIntegerValidator isIntegerValidator = new IsIntegerValidator();
isIntegerValidator.setErrorMessage("error message");
textItem.setValidators(isIntegerValidator);
And to show the errors like that when you call the form.validate() you need to set the setShowInlineErrors(true) in the form.
What about limiting characters that can be entered by the user?
Please see this sample:
http://www.smartclient.com/smartgwt/showcase/#form_keypress_filter

How do you create a simple Automation Extender for Visual Studio with UITypeEditor

In Visual Studio when you select project or project items in the solution explorer there are times when you might want to add custom properties to the properties window(the window that pops up when you press F4). Also, to fill in the values of those properties I need to add a button to pop up a form so I can collect information from the user at design time.
What is the simplest implementation of this so I can get started?
How would I create a user interface to collect the value some how by using UITypeEditAttribute?
This is the simplest implementation I could come up with.
Since this is an advanced topic, it is implied that you feel comfortable with completing all the steps before you start the implementation(these are all common programming tasks).
If anything is not clear enough just comment and I will try to simplify. Note that this is configured to create a custom property for a Visual C# file within visual studio. When you run or debug your visual studio package followed by clicking any .cs file, the custom property should show in the properties window. The comments provided are required instructions.
Create a Visual Studio package.
Create an interface that implements the custom properties that you would like to add to the properties page.
Create a class that implements the custom property interface and decorate the custom property with attributes.
Create class that implements IExtenderProvider interface and override GetExtender and CanExtend methods.
Create a new class that inherits from UITypeEditor and override GetEditStyle and EditValue methods.
Let's get started.
1. Create Package in visual studio.
Package.cs
// ...
public sealed class ThePackage : Package
{
private DTE2 Host;
private ObjectExtenders _extensionManager;
private MyExtenderProvider _extenderProvider;
protected override void Initialize()
{
Host = (DTE2)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SDTE));
_extenderProvider = new MyExtenderProvider();
_extenderProviderCookie = Host.ObjectExtenders.RegisterExtenderProvider(VSConstants.CATID.CSharpFileProperties_string,
"MyExtenderProvider", _extenderProvider);
}
protected override void Dispose(bool disposing)
{
Host.ObjectExtenders.UnregisterExtenderProvider(_extenderProviderCookie);
_extenderProvider = null;
base.Dispose(disposing);
}
}
2. Create class that implements your desired custom properties.
[ComVisible(true)] // Important!
public interface IMyDynamicExtender
{
String NewProperty { get; set; }
}
3. Create a class that implements the custom property interface.
[ComVisible(true)] // Important!
public class NewPropertyExtender : IMyDynamicExtender, IDisposable
{
// These attibutes supply the property with some information
// on how to display and which UITypeEditor to use.
[DisplayName("New Property")]
[Category("New")]
[Description("Specifies the new property")]
[Editor(typeof(CustomUiTypeEditor), typeof(UITypeEditor))]
public String NewProperty { get; set; }
private readonly IExtenderSite _extenderSite;
private readonly int _cookie;
private bool _disposed;
public NewPropertyExtender(IExtenderSite extenderSite, int cookie)
{
_extenderSite = extenderSite;
_cookie = cookie;
}
public void Dispose()
{
Dispose(true);
// take the instance off of the finalization queue.
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing && _cookie != 0)
{
_extenderSite.NotifyDelete(_cookie);
}
_disposed = true;
}
}
4. Create class that implements [IExtenderProvider] interface and override [GetExtender] and [CanExtend] methods.
public class MyExtenderProvider : IExtenderProvider
{
private IMyDynamicExtender _extender;
public object GetExtender(string extenderCatid, string extenderName,
object extendeeObject, IExtenderSite extenderSite,
int cookie)
{
return _extender = CanExtend(extenderCatid, extenderName, extendeeObject) ?
new NewPropertyExtender(extenderSite, cookie) : null;
}
public bool CanExtend(string extenderCatid, string extenderName, object extendeeObject)
{
// Some implementation will be here in the real world.
return true;
}
}
5. Create a new class that inherits from [UITypeEditor] and override [GetEditStyle] and [EditValue] methods.
public class CustomUiTypeEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
// Use the result of a dialog or something else here.
return "HELLO WORLD";
}
}

How to exclude feedback messages from a specific child component/container?

I would like to filter messages coming to my feedback panel by excluding a specific child component or container. Is there a way to do this?
Wicket currently has a ContainerFeedbackMessageFilter and ComponentFeedbackMessageFilter. The container will filter everything from children of the specified container while the component one filters only from that component.
My goal is to have all components except the specified one display their feedback messages.
Roll your own IFeedbackMessageFilter that accepts from any component but the one you want to be ignored.
You can create your own implementation of IFeedbackMessageFilter and iterate through the message reporter's parents to see if one of the parents is a class you'd like to exclude from reporting to the parent feedback panel.
This is a little hacky with the class checking but it works for what I needed:
public class ExcludeClassFeedbackMessageFilter implements IFeedbackMessageFilter {
private static final long serialVersionUID = -8104563974910018990L;
private MarkupContainer parentContainer;
private Class<?>[] classes;
public ExcludeClassFeedbackMessageFilter(MarkupContainer parentContainer, Class<?>... classes) {
this.parentContainer = parentContainer;
this.classes = classes;
}
#Override
public boolean accept(FeedbackMessage message) {
Component reporter = message.getReporter();
boolean foundExcludedComponent = false;
Component parent = reporter.getParent();
while (!(parent.equals(parentContainer))) {
for (Class<?> clazz : classes) {
if (parent.getClass().getName().contains(clazz.getName())) {
foundExcludedComponent = true;
}
}
parent = parent.getParent();
}
return !foundExcludedComponent;
}
}

How and Where to tell if a ViewComponent has been invoked x times in a view?

I have a ViewComponent that I need to invoke twice only! How and where can I tell the invokations count?
Currently I can use a session but I dislike using session in mvc apps! How may I achieve this?
namespace Partials.Components
{
public class MyComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
Session["invoked"]=(int)Session["invoked"]+1;
var model = new{
Website="Stack Overflow",
Url="www.http://stackoverflow.com"
};
return View("_MyComponent ", model);
}
}
}
and in my view
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Session["invoked"]</span> times</span>
You can use TempData. It persists only until the next request.
TempData["invoked"]=(int)TempData["invoked"]+1;
View:
<span>Invoked ViewComponent <span>#TempData["invoked"]</span> times</span>
Note: TempData uses session under the covers.
You can use HttpContext.Items which has the advantage of not using the session. These items are stored and shared per request, which would also fit your objective.
In your viewComponent you can add/retrieve an item as in this.Context.Items["MyComponentInvocationCount"]. Whenever the count is greater than 2 you can just return an empty content with return Content(String.Empty).
You can combine that with an extension method so you can get the count from outside that class:
[ViewComponent(Name = "MyComponent")]
public class MyViewComponent : ViewComponent
{
internal static readonly string ContextItemName = "InvocationCount";
public IViewComponentResult Invoke()
{
this.InvocationCount = this.InvocationCount + 1;
if (this.InvocationCount > 2) return Content(String.Empty);
//return your content here
return Content("Can be invoked");
}
private int InvocationCount
{
get
{
return this.Context.InvocationCount();
}
set
{
this.Context.Items[ContextItemName] = value;
}
}
}
public static class MyViewComponentExtensions
{
public static int InvocationCount(this HttpContext context)
{
var count = context.Items[MyViewComponent.ContextItemName];
return count == null ? 0 : (int)count;
}
}
Then you could use it in a view as follows:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount()</span> times</span>
If you add the above lines 3 times in a view, you will see that the third one does not add any content.
EDIT - Using ViewComponentInvoker
I have been exploring how to implement this feature adding a custom ViewComponentInvoker.
I started by adding a new attribute that can be used to decorate ViewComponents so they are limited to a certain number of invocations per request:
public class PerRequestInvocationLimitAttribute: Attribute
{
public int PerRequestInvocationLimit { get; set; }
}
You would then create your view component as usual, the only change being adding this attribute:
[PerRequestInvocationLimit(PerRequestInvocationLimit = 2)]
public class MyViewComponent : ViewComponent
{
//implementation of view component
}
We can then create a custom IViewComponentInvoker that decorates the DefaultViewComponentInvoker.
This custom view component invoker will keep track of the number of
times a view component has been invoked in the current request.
When a view component that has the new attribute is invoked, it will only
really invoke it if the number of invocations is below the limit.
Implementing this view component invoker looks like:
public class LimitedPerRequestViewComponentInvoker : IViewComponentInvoker
{
private readonly IViewComponentInvoker _defaultViewComponentInvoker;
public LimitedPerRequestViewComponentInvoker(IViewComponentInvoker defaultViewComponentInvoker)
{
this._defaultViewComponentInvoker = defaultViewComponentInvoker;
}
public void Invoke(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return;
this._defaultViewComponentInvoker.Invoke(context);
}
public Task InvokeAsync(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return Task.WhenAll();
return this._defaultViewComponentInvoker.InvokeAsync(context);
}
private bool CanInvokeViewComponent(ViewComponentContext context)
{
// 1. Increase invocation count
var increasedCount = context.ViewContext.HttpContext.IncreaseInvocationCount(
context.ViewComponentDescriptor.ShortName);
// 2. check if there is any limit for this viewComponent, if over the limit then return false
var limitAttribute = context.ViewComponentDescriptor.Type
.GetCustomAttributes(true)
.OfType<PerRequestInvocationLimitAttribute>()
.FirstOrDefault();
if (limitAttribute != null && limitAttribute.PerRequestInvocationLimit < increasedCount)
{
return false;
}
// 3. There is no limit set or the limit has not been reached yet
return true;
}
}
It uses some extension methods to set/get the invocation count from HttpContext.Items (That you could also use in your view to get the number of times a view component was invoked)
public static class ViewComponentExtensions
{
public static int InvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.Items[GetHttpContextItemsName(viewComponentName)];
return count == null ? 0 : (int)count;
}
internal static int IncreaseInvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.InvocationCount(viewComponentName);
context.Items[GetHttpContextItemsName(viewComponentName)] = ++count;
return count;
}
private static string GetHttpContextItemsName(string viewComponentName)
{
return string.Format("InvocationCount-{0}", viewComponentName);
}
}
The final piece is to create a new IViewComponentInvokerFactory replacing the default one, so it creates an instance of the new custom view component invoker instead of the default one. You also need to register it on Startup.cs:
public class MyViewComponentInvokerFactory : IViewComponentInvokerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ITypeActivatorCache _typeActivatorCache;
private readonly IViewComponentActivator _viewComponentActivator;
public MyViewComponentInvokerFactory(IServiceProvider serviceProvider, ITypeActivatorCache typeActivatorCache, IViewComponentActivator viewComponentActivator)
{
_serviceProvider = serviceProvider;
_typeActivatorCache = typeActivatorCache;
_viewComponentActivator = viewComponentActivator;
}
public IViewComponentInvoker CreateInstance(ViewComponentDescriptor viewComponentDescriptor, object[] args)
{
return new LimitedPerRequestViewComponentInvoker(
new DefaultViewComponentInvoker(_serviceProvider, _typeActivatorCache, _viewComponentActivator));
}
}
//Configure the ViewComponentInvokerFactory in Startup.ConfigureServices
services.AddTransient<IViewComponentInvokerFactory, MyViewComponentInvokerFactory>();
With all these pieces in place, you can use your view component 3 times and you will see how it will be rendered only twice:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount("MyComponent")</span> times</span>
I prefer this solution for a few reasons:
It is based on the hooks provided by the new mvc framework.
Does not need changes to your view component, other than adding the attribute that sets the invocation limit.
It works when invoking view component asynchronously.

Get clicked cell from headertable in bodytable

I'm trying to get the clicked cell in a headertable to do sorting, but I want to handle this in another class, the class that implements the table. If I write out the cell in the headertable class is prints the right cell id, but when adding the clickhandler to the implementing class the id is always 0.
Example:
public class CustomerDetailsHoldingsTable extends SimpleTable<Holding>
implements ClickHandler {
TableDataSource<Holding> ds;
Public CustomerDetailsHoldingsTable () {
this.headerTable = new HeaderTable();
this.headerTable.addClickHandler(this);
}
#Override
public void onClick(ClickEvent event) {
GWT.log("Clicked cell with id" +
getCellForEvent(event).getCellIndex());
}
public class HeaderTable extends Grid {
...
...
}
The GWT.log line always prints 0 regardless what cell is clicked in the headertable. Why is that?
You'll need to invoke getCellForEvent on your grid object, like so:
#Override
public void onClick(ClickEvent event) {
GWT.log("Clicked cell with id" +
this.headerTable.getCellForEvent(event).getCellIndex());
}
From the docs:
Given a click event, return the Cell
that was clicked, or null if the event
did not hit this table. The cell can
also be null if the click event does
not occur on a specific cell.

Resources