JavaFX 2.0 - create action handler for custom component in FXML - custom-controls

I want to add a custom action in my new component.
How to do this?
Example code:
Component
public class MyCustomComponent extends Region {
public MyCustomComponent(){
super();
this.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
/* throw my custom event here and handle it in my FXML controller - but how? :-( */
}
});
}
}
Controller
public class MyController {
#FXML protected void myCustomAction(ActionEvent event) {
// do something
}
}
FXML:
<BorderPane fx:controller="fxmlexample.MyController"
xmlns:fx="http://javafx.com/fxml">
<top>
<MyCustomComponent onAction="#myCustomAction">
</MyCustomComponent>
</top>
</BorderPane>
Thx for help

You need to implement property in your custom component, which will store your action.
public class MyCustomComponent extends Region {
public MyCustomComponent(){
super();
// just to find out where to click
setStyle("-fx-border-color:red;");
setPrefSize(100, 100);
this.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
onActionProperty().get().handle(event);
}
});
}
// notice we use MouseEvent here only because you call from onMouseEvent, you can substitute any type you need
private ObjectProperty<EventHandler<MouseEvent>> propertyOnAction = new SimpleObjectProperty<EventHandler<MouseEvent>>();
public final ObjectProperty<EventHandler<MouseEvent>> onActionProperty() {
return propertyOnAction;
}
public final void setOnAction(EventHandler<MouseEvent> handler) {
propertyOnAction.set(handler);
}
public final EventHandler<MouseEvent> getOnAction() {
return propertyOnAction.get();
}
}
and don't forget to add import in your fxml file:
<?import my.package.MyCustomComponent?>

Related

How to re-render Wicket component after the Event reception

I have a Wicket component which is listening for some event (IEvent). If such event arrives, I want to re-render the component with a changed model. There are no active controls on the page, like AjaxLink, which can trigger the re-rendering.
Is there a way to refresh such kind of component?
I was thinking to somehow trigger an AJAX request from the onEvent method and add an AjaxBehavior to the mentioned component. But I don't know, how to trigger the AJAX request.
public class PersonPanel extends Panel implements Observer {
private WebMarkupContainer wrapper;
public PersonPanel(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));
wrapper = new WebMarkupContainer("wrapper");
wrapper.setOutputMarkupId(true);
add(wrapper);
wrapper.add(new Label("personID"));
// some more content
}
private IModel<PersonInfo> getModel() {
return new LoadableDetachableModel<PersonInfo>() {
#Override
protected PersonInfo load() {
// model loading logic
}
};
}
#Override
public void onEvent(IEvent<?> event) {
logger.debug("\n Person Panel received an Event: " + event.getPayload());
// Re-rendering of "wrapper" should be triggered from here.
}
#Override
public void update(Observable observable, Object o) {
send(this, Broadcast.EXACT, "Observable cache has changed.");
}
}
Here is the solution, thanks to hint from martin-g, solved via WebSockets. See the methods update and onEvent, plus added WebSocketBehavior on the component:
public class PersonPanel extends Panel implements Observer {
private WebMarkupContainer wrapper;
public PersonPanel(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));
wrapper = new WebMarkupContainer("wrapper");
wrapper.setOutputMarkupId(true);
add(wrapper);
wrapper.add(new Label("personID"));
// some more content
add(new WebSocketBehavior() {
});
observableCache.addObserver(this);
}
private IModel<PersonInfo> getModel() {
return new LoadableDetachableModel<PersonInfo>() {
#Override
protected PersonInfo load() {
// model loading logic
}
};
}
#Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof WebSocketPushPayload) {
WebSocketPushPayload wsEvent = (WebSocketPushPayload) event.getPayload();
wsEvent.getHandler().add(wrapper);
}
}
#Override
public void update(Observable observable, Object o) {
WebSocketSettings webSocketSettings =
WebSocketSettings.Holder.get(getApplication());
WebSocketPushBroadcaster broadcaster =
new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
broadcaster.broadcastAll(
getApplication(),
new WebSocketMessage("WebSocket message from the PersonPanel."));
}
}
You can find a full running example project, implemented in Wicket 8 and Gradle on Bitbucket:
sw-samuraj/blog-wicket-spring-rest
At the send side you can pass the AjaxRequestTarget with the payload of the event.
send(getPage(), Broadcast.DEPTH, new MyPayload(target));
and then on the receive side:
MyPayload payload = (MyPayload) event.getPayload();
payload.getTarget().add(this);

how to set cub out effect in viewpager with different fragmaents / layouts

my viewpager is different (with multy xml and java file.means page1 java and xml file,page2 java and xml file,page3 java and xml files are seprate).
and want to sate cubeout effect in my viewpager.
**this is my coad **
public class MercuryActivity extends FragmentActivity implements OnPageListener {
List fragments = new Vector();
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.fragments.add(Fragment.instantiate(this, Page1Fragment.class.getName()));
this.fragments.add(Fragment.instantiate(this, Page2Fragment.class.getName()));
this.fragments.add(Fragment.instantiate(this, Page3Fragment.class.getName()));
this.fragments.add(Fragment.instantiate(this, Page4Fragment.class.getName()));
this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), this.fragments);
this.mPager = (ViewPager) super.findViewById(R.id.pager);
this.mPager.setAdapter(this.mPagerAdapter);
}
public void onPage1(String s) {
((Page2Fragment) this.fragments.get(1)).getView();
((Page3Fragment) this.fragments.get(2)).getView();
((Page4Fragment) this.fragments.get(3)).getView();
}
public void onBackPressed() {
new Builder(this).setIcon(17301543).setTitle("Exit").setMessage("Are you sure you want to exit?").setPositiveButton("Yes", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
MercuryActivity.this.moveTaskToBack(true);
MercuryActivity.this.finish();
}
}).setNegativeButton("No", null).show();
}
}
and this is my page adapter
public class PagerAdapter extends FragmentPagerAdapter {
private List fragments;
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
public Fragment getItem(int position) {
return (Fragment) this.fragments.get(position);
}
public int getCount() {
return this.fragments.size();
}
}

Invalid void error and illegal modifier error

I keep getting this error:
Illegal modifier for the local class myWebClient; only abstract or final is permitted.
and this error:
void is an invalid type for the variable backButtonClicked
Heres the code where the error occurs.
public class myWebClient extends WebViewClient
{
}
public void backButtonClicked(View view)
{
if (ourBrow.canGoBack())
ourBrow.goBack();
}
public void forwardButtonClicked(View view)
{
if (ourBrow.canGoForward())
ourBrow.goForward();
}
public void goButtonClicked(View view)
{
String theWebsite = Url.getText().toString();
if(theWebsite != null)
ourBrow.loadUrl(theWebsite);
}
public void refreshButtonClicked(View view)
{
ourBrow.reload();
}
Remove the public modifier of the class and put all methods inside the body of the class:
class myWebClient extends WebViewClient
{
public void backButtonClicked(View view)
{
if (ourBrow.canGoBack())
ourBrow.goBack();
}
public void forwardButtonClicked(View view)
{
if (ourBrow.canGoForward())
ourBrow.goForward();
}
public void goButtonClicked(View view)
{
String theWebsite = Url.getText().toString();
if(theWebsite != null)
ourBrow.loadUrl(theWebsite);
}
public void refreshButtonClicked(View view)
{
ourBrow.reload();
}
}

AjaxLink updateAjaxAttributes - AjaxCallListener getPrecondition

I stucked during migration from Wicket 1.5 to 6.6.
Earlier AjaxLink allowed to override getAjaxCallDecorator() method and wrap the script with preDecorateScript(CharSequence script).
Now recommended way is using AjaxCallListener with getPrecondition(Component component) method. But how can I wrap the source script using Component component parameter?
Dont know if i understand you correctly. We do it this way:
public class MyAjaxCallListener implements IAjaxCallListener{
#Override
public CharSequence getBeforeHandler(Component component) {
return null;
}
#Override
public CharSequence getPrecondition(Component component) {
return YOUR_SCRIPT;
}
// ... not needed overrides can return null
}
Then you add it through an Behavior to your AjaxLink.
ajaxLink.add(new AjaxEventBehavior("onclick") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
//do stuff
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new MyAjaxCallListener());
}
});

Castle Windsor: master controller not resolving the registered components in the container

Having the code below in my Global.asax.cs and two controller (one based on a the other: MasterController) I don't seem to find how can I resolve the repository register in my WindsorContainer from the MasterController... the same applies in the HomeController and works perfectly... what am I doing wrong?
Global.asax.cs:
private IWindsorContainer _container;
protected void Application_Start()
{
InitializeContainer();
RegisterRoutes(RouteTable.Routes);
}
protected void Application_End()
{
this._container.Dispose();
}
protected void Application_EndRequest()
{
if (_container != null)
{
var contextManager = _container.Resolve<IContextManager>();
contextManager.CleanupCurrent();
}
}
private void InitializeContainer()
{
_container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
// Register context manager.
_container.Register(
Component.For<IContextManager>()
.ImplementedBy<EFContextManager>()
.LifeStyle.Singleton
.Parameters(
Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
)
);
//Products repository
_container.Register(
Component.For<IProductRepository>()
.ImplementedBy<ProductRepository>()
.LifeStyle.Singleton
);
// Register all MVC controllers
_container.Register(AllTypes.Of<IController>()
.FromAssembly(Assembly.GetExecutingAssembly())
.Configure(c => c.LifeStyle.Transient)
);
}
Controller base:
public class MasterController : Controller
{
private IProductRepository _productRepository;
public ProductController(IProductRepository product)
{
_productRepository = product;
}
public ActionResult Index()
{
ViewData["product"] = _productRepository.FindOne(123);
return View();
}
}
Controller based on MasterController:
public class ProductController : MasterController
{
private IProductRepository _productRepository;
public ProductController(IProductRepository product)
{
_productRepository = product;
}
public ActionResult Search(int id)
{
ViewData["product"] = _productRepository.FindOne(id);
return View();
}
}
It is working as expected now and the ViewDatas are accessible from any controller/view.
First I created a public class where I store my Windsor container so it can be accessed from any controller:
public static class IOCcontainer
{
public static IWindsorContainer Container { get; set; }
}
Then in my global.asax.cs I have:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
InitializeContainer();
}
private void InitializeContainer()
{
_container = new WindsorContainer();
// Register context manager.
_container.Register(
Component.For<IContextManager>()
.ImplementedBy<EFContextManager>()
.LifeStyle.Singleton
.Parameters(
Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
)
);
//Products repository
_container.Register(
Component.For<IProductRepository>()
.ImplementedBy<ProductRepository>()
.LifeStyle.Singleton
);
// Register all MVC controllers
_container.Register(AllTypes.Of<IController>()
.FromAssembly(Assembly.GetExecutingAssembly())
.Configure(c => c.LifeStyle.Transient)
);
IOCcontainer.Container = _container; //set the container class with all the registrations
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}
So now in my master controller I can use:
public class MasterController : Controller
{
private IProductRepository g_productRepository;
public MasterController() : this(null,null,null,null,null)
{
}
public MasterController(IProductRepository productRepository)
{
g_productRepository = productRepository ?? IOCcontainer.Container.Resolve<IProductRepository>();
}
//I don't use an action here, this will make execute it for any action in any controller
protected override void OnActionExecuting(ActionExecutingContext context)
{
if (!(context.ActionDescriptor.ActionName.Equals("Index") && context.Controller.ToString().IndexOf("Home")>0)) {
//I now can use this viewdata to populate a dropdownlist along the whole application
ViewData["products"] = g_productRepository.GetProducts().ToList().SelectFromList(x => x.Id.ToString(), y => y.End.ToShortDateString());
}
}
}
Then the rest of controllers:
//will be based on MasterController
public class AboutController : MasterController
{
}
public ActionResult Index()
{
return View();
}
etc...
Probably not the most elegant way to do it but it will do until I find a better way or someone else brighten my mind up!

Resources