Eclipse Scout modal view error - eclipse-scout

I am working in new Scout Neon and I am starting to get error :
Assertion error: Property 'modal' cannot be changed because Form is already showing
My forms has properties :
#Override
protected int getConfiguredModalityHint() {
return MODALITY_HINT_MODELESS;
}
#Override
protected int getConfiguredDisplayHint() {
return DISPLAY_HINT_VIEW;
}
#Override
protected String getConfiguredDisplayViewId() {
return VIEW_ID_CENTER;
}
What I did wrong?
EDIT : Marko
I add page in MyOutline witch extends from AbstractOutline
public class MyOutline extends AbstractOutline {
#Override
protected String getConfiguredTitle() {
return TEXTS.get("MyOutline");
}
#Override
protected void execCreateChildPages(final List<IPage<?>> pageList) {
final MyPage myPage = new MyPage();
pageList.add(myPage);
super.execCreateChildPages(pageList);
}
}
MyPage is only a wrapper page for form.
public class MyPage extends AbstractPageWithNodes {
#Override
protected boolean getConfiguredLeaf() {
return true;
}
#Override
protected boolean getConfiguredTableVisible() {
return false;
}
#Override
protected String getConfiguredTitle() {
return TEXTS.get("MyPage");
}
#Override
protected Class<? extends IForm> getConfiguredDetailForm() {
return MyForm.class;
}
}
and my form is nothing spacial :
#FormData(value = MyFormData.class, sdkCommand = FormData.SdkCommand.CREATE)
public class MyForm extends AbstractForm {
/**
* Method start Form for adding new person.
*/
public void startNew() {
this.startInternal(new NewHandler());
}
#Override
protected boolean getConfiguredAskIfNeedSave() {
return false;
}
#Override
protected int getConfiguredModalityHint() {
return MODALITY_HINT_MODELESS;
}
#Override
protected int getConfiguredDisplayHint() {
return DISPLAY_HINT_VIEW;
}
#Override
protected String getConfiguredDisplayViewId() {
return VIEW_ID_CENTER;
}
public MainBox getMainBox() {
...
But when I want to open this Page (on start application is not opened on this page), (and I do not do anything else before) I get error.
2016-01-22 11:13:56,236 ERROR scout-model-thread-11 'Processing JSON request' o.e.scout.rt.platform.exception.ExceptionHandler -
org.eclipse.scout.rt.platform.util.Assertions$AssertionException: Assertion error: Property 'modal' cannot be changed because Form is already showing
at org.eclipse.scout.rt.platform.util.Assertions.fail(Assertions.java:581) ~[org.eclipse.scout.rt.platform-5.2.0.M4.jar:5.2.0.M4]
at org.eclipse.scout.rt.platform.util.Assertions.assertFalse(Assertions.java:192) ~[org.eclipse.scout.rt.platform-5.2.0.M4.jar:5.2.0.M4]
at org.eclipse.scout.rt.client.ui.form.AbstractForm.setModal(AbstractForm.java:2700) ~[org.eclipse.scout.rt.client-5.2.0.M4.jar:5.2.0.M4]
at org.eclipse.scout.rt.client.ui.desktop.outline.pages.AbstractPage.decorateDetailForm(AbstractPage.java:692) ~[org.eclipse.scout.rt.client-5.2.0.M4.jar:5.2.0.M4]

I found solution for my problem.
in my constructor in form I have :
public PersonsExtensionFieldForm() {
this.startInternal(new NewHandler());
}
witch is ok, when you open form from other form with for example button click.
But when you put form in page as Detail form you need to have
public PersonsExtensionFieldForm() {
this.setHandler(new NewHandler());
}

Related

Tab Create Event Handler

In my code, MyTab extendes Tab and until version 8 existed the method setEventHandler (...);
As I am now using the javaFX 12 version, this method is private and I can not use it anymore.
I also do not have access to the variable eventHandlerManager of Tab.
How can I access this functionality in JavaFX 12?
Here is an example of the code.
public class MyTab extends Tab {
...
protected ObjectProperty<EventHandler<EventAction>> onEventDockRequest=null;
public void setOnEventDockRequest(EventHandler<EventAction> value) {
onEventDockRequestProperty().set(value);
}
public final ObjectProperty<EventHandler<EventAction>> onEventDockRequestProperty() {
if (onEventDockRequest == null) {
onEventDockRequest = new ObjectPropertyBase<EventHandler<EventAction>>() {
#Override protected void invalidated() {
setEventHandler(EventAction.DOCK_REQUEST, get()); // here error
}
#Override public Object getBean() {
return DTab.this;
}
#Override public String getName() {
return "onEventDockRequest";
}
};
}
return onEventDockRequest;
}
}

JavaFX: Custom TableViewSelectionModel

I have a TableView which lists several addresses as a preview. The selected address can be edited in a form next to the TableView. In case that the user has made changes to the selected address and changes the selected address in the TableView, I want to ask him if he wants to proceed without saving changes. If no, I want the Tableview to stay at the currently selected position, if the user wants to discard the changes the TableView may perform the selection change.
My approach would have been to extend the SelectionModel of the TableView and only allow the selection to change if the user answers the described dialog or there are no changes. Basically I only want to add an if-clause before changing the selection in the Tableview. Unfortunately, I only found the abstract class “TableViewSelectionModel” and no concrete implementations of it.
Is there any way to obtain this desired behavior without implementing the whole class?
Solved it with James_D's recommendation:
public class ControllableTableSelectionModel<T> extends TableViewSelectionModel<T>{
private TableViewSelectionModel<T> originalModel;
private ControlsTableView controller;
public ControllableTableSelectionModel(TableViewSelectionModel<T> originalModel, ControlsTableView controller) {
super(originalModel.getTableView());
this.originalModel=originalModel;
this.controller=controller;
}
#Override
public boolean isSelected(int row, TableColumnBase<T, ?> column) {
return originalModel.isSelected(row, column);
}
#Override
public void selectLeftCell() {
if(controller.canSelect(this))
{
originalModel.selectLeftCell();
}
}
#Override
public void selectRightCell() {
if(controller.canSelect(this))
{
originalModel.selectRightCell();
}
}
#Override
public void selectAboveCell() {
if(controller.canSelect(this))
{
originalModel.selectAboveCell();
}
}
#Override
public void selectBelowCell() {
if(controller.canSelect(this))
{
originalModel.selectBelowCell();
}
}
#Override
public void selectRange(int minRow, TableColumnBase<T, ?> minColumn, int maxRow,
TableColumnBase<T, ?> maxColumn) {
if(controller.canSelect(this))
{
originalModel.selectRange(minRow, minColumn, maxRow, maxColumn);
}
}
#Override
protected int getItemCount() {
return originalModel.getTableView().getItems().size();
}
#Override
protected T getModelItem(int index) {
return originalModel.getTableView().getItems().get(index);
}
#Override
public void focus(int index) {
originalModel.getTableView().getFocusModel().focus(index);
}
#Override
public int getFocusedIndex() {
return originalModel.getTableView().getFocusModel().getFocusedIndex();
}
#Override
public ObservableList<TablePosition> getSelectedCells() {
return originalModel.getSelectedCells();
}
#Override
public boolean isSelected(int row, TableColumn<T, ?> column) {
return originalModel.isSelected(row, column);
}
#Override
public void select(int row, TableColumn<T, ?> column) {
if(controller.canSelect(this))
{
originalModel.select(row, column);
}
}
#Override
public void clearAndSelect(int row, TableColumn<T, ?> column) {
if(controller.canSelect(this))
{
originalModel.clearAndSelect(row, column);
}
}
#Override
public void clearSelection(int row, TableColumn<T, ?> column) {
if(controller.canSelect(this))
{
originalModel.clearSelection(row, column);
}
}
}
I'd like to add an improvement to your self-answer by making it more generic and applying the "tell, don't ask!" principle:
public class ControllableTableSelectionModel<T> extends TableViewSelectionModel<T> {
#FunctionalInterface
public interface VetoableSelectAction{
void execute();
}
#FunctionalInterface
public interface SelectionVeto {
<T> void allow(TableViewSelectionModel<T> tableViewSelectionModel, SelectionVeto vetoableSelectAction);
}
private final TableViewSelectionModel<T> originalModel;
private final SelectionVeto selectionVeto;
public ControllableTableSelectionModel(TableViewSelectionModel<T> originalModel, SelectionVeto selectionVeto) {
super(originalModel.getTableView());
this.originalModel = originalModel;
this.selectionVeto = selectionVeto;
}
#Override
public boolean isSelected(int row, TableColumnBase<T, ?> column) {
return originalModel.isSelected(row, column);
}
#Override
public void selectLeftCell() {
selectionVeto.allow(this, () -> originalModel.selectLeftCell());
}
// ...
}
I personally have no use for the second parameter in allow():
public class ControllableTableSelectionModel<T> extends TableViewSelectionModel<T> {
// ...
#FunctionalInterface
public interface SelectionVeto{
void allow(VetoableSelectAction vetoableSelectAction);
}
// ...
#Override
public void selectLeftCell() {
selectionVeto.allow(() -> originalModel.selectLeftCell());
}
// ...
}

Using IPageDialogService in OnNavigatedTo on app startup

I've created a Prism Unity App using the Prism Template Pack and added another View and ViewModel (OtherPage and OtherPageViewModel) to it. This is my code:
App.xaml.cs
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
NavigationService.NavigateAsync("MainPage?title=Hello%20from%20Xamarin.Forms");
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<MainPage>();
Container.RegisterTypeForNavigation<OtherPage>();
}
}
MainPageViewModel.cs
public class MainPageViewModel : BindableBase, INavigationAware
{
private INavigationService _navigationService;
private IPageDialogService _pageDialogService;
public DelegateCommand NavigateToOtherPageCommand { get; set; }
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainPageViewModel(INavigationService navigationService,
IPageDialogService pageDialogService)
{
_navigationService = navigationService;
_pageDialogService = pageDialogService;
NavigateToOtherPageCommand = new DelegateCommand(async () => await NavigateToOtherPage());
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public async void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters.ContainsKey("title"))
Title = (string)parameters["title"] + " and Prism";
await _pageDialogService.DisplayAlertAsync("Message", "Message for the user", "Ok");
}
private async Task NavigateToOtherPage()
{
await _navigationService.NavigateAsync("OtherPage");
}
}
OtherPageViewModel.cs
public class OtherPageViewModel : BindableBase, INavigationAware
{
private IPageDialogService _pageDialogService;
public OtherPageViewModel(IPageDialogService pageDialogService)
{
_pageDialogService = pageDialogService;
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public async void OnNavigatedTo(NavigationParameters parameters)
{
await _pageDialogService.DisplayAlertAsync("Message", "Message for the user", "Ok");
}
}
I'm attempting to use the IPageDialogService to display a message to the user in the MainPageViewModels's OnNavigatedTo method but no message is displayed and no error is raised.
However, if I navigate from MainPage to OtherPage using the NavigateToOtherPageCommand, the message is displayed correctly. Why doesn't the IPageDialogService work in the OnNavigatedTo method of the startup page (i.e MainPageViewModel)? It seems to work fine in the OnNavigatedTo method of any other page (i.e OtherPageViewModel).
Try to use await Task.Yield(). More information about this issue in this link: pageDialogService MainPage reference is always null inside OnNavigatedTo after app is launched

Custom Observable List implementation, notifying consumers of changes

I have created a custom ObservableList implementation for a list of TreeItems. My custom implementation can listen to various notifications from inside my app (using OSGi EventAdmin), and update itself accordingly. I then expect its consumer (a TreeView widget) to be updated with the changes to the list. However, I can't see how to notify the consumer.
In the ObservableList subclass I am implementing addListener(ListChangeListener), which I would expect to get called when the object is added to the widget. However it is never called; I have no listeners thus no apparent way to notify anyone when the list changes. I must be missing something.
Here is a snippet from my TreeItem implementation, which returns an instance of my ObservableList in response to a getChildren call:
#Override
public ObservableList<TreeItem<DataObject>> getChildren() {
if (needChildren) {
needChildren = false;
children = new MyObservableList();
}
return children;
}
Here is an abridged version of my custom ObservableList implementation, which simply wraps an FXCollections.observableArrayList and adds an OSGi event handler. I listen to changes on the internal list so that I can pass those changes on to my listeners.
public class MyObservableList implements ObservableList<TreeItem<DataObject>>, EventHandler {
private List<ListChangeListener<? super TreeItem<DataObject>>> changeListeners = new ArrayList<>();
private List<InvalidationListener> invalidationListeners = new ArrayList<>();
private ObservableList<TreeItem<DataObject>> theList;
private int size;
public MyObservableList() {
theList = FXCollections.observableArrayList();
theList.addListener(new ListChangeListener<TreeItem<DataObject>>() {
#Override
public void onChanged(Change<? extends TreeItem<DataObject>> change) {
fireValueChangedEvent(change);
}
});
}
#Override
public int size() {
return theList.size();
}
#Override
public boolean isEmpty() {
return (size == 0);
}
#Override
public boolean contains(Object o) {
return theList.contains(o);
}
#Override
public Iterator iterator() {
return theList.iterator();
}
#Override
public boolean remove(Object o) {
return theList.remove(o);
}
#Override
public boolean addAll(Collection c) {
return theList.addAll(c);
}
#Override
public boolean addAll(int index, Collection c) {
return theList.addAll(index, c);
}
#Override
public void clear() {
theList.clear();
}
#Override
public TreeItem<DataObject> get(int index) {
return theList.get(index);
}
#Override
public int indexOf(Object o) {
return theList.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return theList.lastIndexOf(o);
}
#Override
public ListIterator listIterator() {
return theList.listIterator();
}
#Override
public ListIterator listIterator(int index) {
return theList.listIterator(index);
}
#Override
public List<TreeItem<DataObject>> subList(int fromIndex, int toIndex) {
return theList.subList(fromIndex, toIndex);
}
#Override
public Object[] toArray(Object[] a) {
return theList.toArray(a);
}
#Override
public void addListener(ListChangeListener<? super TreeItem<DataObject>> listChangeListener) {
changeListeners.add(listChangeListener);
}
#Override
public void removeListener(ListChangeListener<? super TreeItem<DataObject>> listChangeListener) {
changeListeners.remove(listChangeListener);
}
#Override
public boolean addAll(TreeItem<DataObject>... treeItems) {
return theList.addAll(treeItems);
}
#Override
public boolean setAll(TreeItem<DataObject>... treeItems) {
return theList.setAll(treeItems);
}
#Override
public boolean setAll(Collection<? extends TreeItem<DataObject>> treeItems) {
return theList.setAll(treeItems);
}
#Override
public boolean removeAll(TreeItem<DataObject>... treeItems) {
return theList.removeAll(treeItems);
}
#Override
public boolean retainAll(TreeItem<DataObject>... treeItems) {
return theList.retainAll(treeItems);
}
#Override
public void remove(int i, int i2) {
theList.remove(i, i2);
}
#Override
public Object[] toArray() {
return theList.toArray();
}
#Override
public boolean add(TreeItem<DataObject> dataObjectTreeItem) {
return theList.add(dataObjectTreeItem);
}
#Override
public boolean containsAll(Collection<?> c) {
return theList.containsAll(c);
}
#Override
public boolean removeAll(Collection<?> c) {
return theList.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return theList.retainAll(c);
}
#Override
public TreeItem<DataObject> set(int index, TreeItem<DataObject> element) {
return theList.set(index, element);
}
#Override
public void add(int index, TreeItem<DataObject> element) {
theList.add(index, element);
}
#Override
public TreeItem<DataObject> remove(int index) {
return theList.remove(index);
}
#Override
public void addListener(InvalidationListener invalidationListener) {
invalidationListeners.add(invalidationListener);
}
#Override
public void removeListener(InvalidationListener invalidationListener) {
invalidationListeners.remove(invalidationListener);
}
private void fireValueChangedEvent(ListChangeListener.Change<? extends TreeItem<DataObject>> change) {
for (ListChangeListener<? super TreeItem<DataObject>> listener : changeListeners) {
listener.onChanged(change);
}
}
#Override
public void handleEvent(Event event) {
// Here I add or remove TreeItem<DataObject> instances to the list based on event.
//
// At this point, onChanged() gets called above in my listener, but my changeListeners list is empty. There is
// no one to pass the Change on to.
}
}
Thanks for any help.
I figured out what's going on here after looking through the JavaFX source.
It turns out that the listening on the ObservableList of children is all set up in the TreeItem itself, not the TreeView as I had somehow assumed. This means that any subclass of TreeView that overrides getChildren() must call super.getChildren() and add its children to the resulting list. This means that using a custom ObservableList implementation is not possible as TreeItem is hardcoded to use FXCollections.observableArrayList() to create the list.
I am taking a different approach to this now where I call super.getChildren(), add my children, and then instantiate another object that holds a reference to that list and does all of my app's event handling business, operating on the list as needed. So my getChildren() method looks something like this now.
private MyEventHandler eventHandler;
private ObservableList<TreeItem<DataObject>> children;
#Override
public ObservableList<TreeItem<DataObject>> getChildren() {
if (needChildren) {
needChildren = false;
children = super.getChildren();
eventHandler = new MyEventHandler(children); // handles app events
}
return children;
}

JSF custom panel with button - action not invoked

I have built a custom component button, but somehow the action is not invoked. When debugging the getAction-Method within the component and invoking the supplied MethodeExpression the Bean-Method is called as expected. But due to some reason, the Expression is not invoked when pressing the button in the browser.
Is there some kind of additional Interface necessary to pass the action to the embedded button-component?
Any help is very appreciated since I am stuck at this issue for some days now
MyClass:
public class MyClass extends UIPanel implements SystemEventListener
{
private UIForm form;
private HtmlCommandButton buttonOk;
public MyClass()
{
FacesContext context = getFacesContext();
UIViewRoot root = context.getViewRoot();
root.subscribeToViewEvent(PostAddToViewEvent.class, this);
}
#Override
public void processEvent(SystemEvent event)
{
this.form = new UIForm();
this.buttonOk = new HtmlCommandButton();
this.buttonOk.setId("okButtonId");
this.buttonOk.setActionExpression(getAction());
this.buttonOk.setValue("OK");
this.form.getChildren().add(this.buttonOk);
getChildren().add(this.form);
}
private enum PropertyKeys
{
action, text, titel
}
public MethodExpression getAction()
{
return (MethodExpression) getStateHelper().eval(PropertyKeys.action);
}
public void setAction(MethodExpression actionExpression)
{
getStateHelper().put(PropertyKeys.action, actionExpression);
}
public String getText()
{
return (String) getStateHelper().eval(PropertyKeys.text);
}
public void setText(String text)
{
getStateHelper().put(PropertyKeys.text, text);
}
public String getTitel()
{
return (String) getStateHelper().eval(PropertyKeys.titel);
}
public void setTitel(String titel)
{
getStateHelper().put(PropertyKeys.titel, titel);
}
#Override
public void encodeAll(FacesContext context) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.DIV_ELEM, this);
writer.writeText(getText(), null);
this.form.encodeAll(context);
writer.endElement(HTML.DIV_ELEM);
}
#Override
public void encodeChildren(FacesContext context) throws IOException
{
}
#Override
public boolean isListenerForSource(Object source)
{
return (source instanceof MyClass);
}
}
MyClassHandler:
public class MyClassHandler extends ComponentHandler
{
public MyClassHandler(ComponentConfig config)
{
super(config);
}
#SuppressWarnings("rawtypes")
#Override
protected MetaRuleset createMetaRuleset(Class type)
{
return super.createMetaRuleset(type).addRule(new MethodRule("action", String.class, new Class[] { ActionEvent.class }));
}
}
myView Method:
...
public String myMethod()
{
System.err.println("myMethod");
return "/some/path/yadayada.xhtml";
}
...
MyView.xhtml
<myTag action="#{myView.myMethod}" id="id1" titel="bla" text="bleh" />
Exdending UICommand is enough, since you only want one action to be executed.
You have to provide two additional MethodExpressions via the tag-attributes and within the decode-method you can check which button has been pressed and redirect the particular MethodExpression to the standard-action provided by UICommand. This way, you dont have to worry about the legacy-interface ActionSource, or how Events are broadcasted.
public void decode(FacesContext contex)
{
Map<String,String> map = context.getExternalContext.getRequestParameterMap();
// your rendered buttons need a name you check for
final boolean okPressed = map.containsKey( getClientId + ":ok" );
final boolean cancelPressed = map.containsKey( getClientId + ":cancel" );
if(okPressed || cancelPressed)
{
MethodExpression exp = null;
if(okPressed)
{
exp = getActionOk();
}
else
{
exp = getActionCancel();
}
// redirect to standard action
setActionExpression(exp);
queueEvent(new ActionEvent(this));
}
}
In order to make use of of this you need two attributes (actionOk and actionCancel) which use Method Expressions (setter and getter). Those have to be configured by a ComponentHandler as you did for the action-attribute.

Resources