Announcement Announcement Module
Collapse
No announcement yet.
Form functionality on an internal frame Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Form functionality on an internal frame

    Hi all,

    I’ve recently made use of RCP-56 in the pet clinic sample and now my app can have multiple views per page.
    I would like to know if it is possible to use the standard features of Form (e.g. validation, models etc..) in a view (JInternalFrame) This is already functional in a ‘dialog’ such as when a New Owner is created.
    Basically I am interested in getting the functionality of the Form in a non-modal InternalFrame... Has anyone achieved this? Could you post an example?
    Thanks in advance,

    Rob

  • #2
    Yes please.

    Hi

    I would also be interested in knowing if it is possible.

    I'd like to use the Form functionality on an internal frame... Anyone?

    Thanks

    Benoit

    Comment


    • #3
      Workaround found... nearly...

      Dear Wob,
      (fan of Looney Tunes?)

      Like you I think that the form-based Dialogs with validation and co are one of the major selling points of Spring RC.

      I am also interested in having such a form put in an internal frame... rather than a modal dialog!

      I have had a quick look and it seems that this functionality (form/validation messages/button bar) can only be in a Dialog.
      I cannot understand why it is the case...

      I think I may have a workaround... and I would like this to be validated by the community, in case it is just too dirty...

      I have written the quintessential Bean/View/Form example which I will include below (there are quite a few bits to it...)
      I have reached the point where I can create a dialog that can be displayed in an internal frame with all bits working.

      Here is the dialog form:
      http://www.objectlab.co.uk/jfree/dialog.jpg

      and when it is displayed part of an internal frame:
      http://www.objectlab.co.uk/jfree/internalframe.jpg

      So, it is great? Not quite...
      1/ I need to create the dialog as usual, it even instantiate a dialog
      2/ I put in the internal frame the ContentPane of the dialog, not the dialog itself as a swing Container cannot accept
      a window. In order add it I do view.add(dialog.getDialog().getContentPane()) and return view from View.createControl().
      3/ but the true issue is that getDialog() will return null... unless you call showDialog() which displays it as a dialog!!!
      This is due to the fact that ApplicationDialog calls createDialog() only in showDialog().

      Would it be possible to change it? Say getDialog() could call createDialog() if dialog is null?
      I think that may be the simplest way... What do the committers think?
      Alternatively, the functionality of form with validation / messages / buttons could be refactored to be independent from a JDialog
      and allow it to be placed in either JDialog or JInternalFrame... But that would be longer term I guess...

      As promised, here is the code:

      The Bean: Test.java
      Code:
      public class Test {
          private String name;
          private String address;
          private String city;
      
          public String getAddress() {
              return address;
          }
      
          public void setAddress(String address) {
              this.address = address;
          }
      
          public String getCity() {
              return city;
          }
      
          public void setCity(String city) {
              this.city = city;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
          
          public Test(String name, String address, String city) {
              this.address = address;
              this.city = city;
              this.name = name;
          }
      }
      The View:
      Code:
      import java.awt.BorderLayout;
      
      import javax.swing.JComponent;
      import javax.swing.JPanel;
      
      import org.springframework.binding.form.ValidatingFormModel;
      import org.springframework.richclient.dialog.TabbedDialogPage;
      import org.springframework.richclient.dialog.TitledPageApplicationDialog;
      import org.springframework.richclient.form.FormModelHelper;
      
      public class TestView extends AbstractView {
          protected JComponent createControl() {
              JPanel view = new JPanel(new BorderLayout());              
              
              // create a form and try to add it to the view...
              ValidatingFormModel model = FormModelHelper.createFormModel(new Test("Benoit","Docklands","London"));
              TestForm form = new TestForm(model);
              
              TabbedDialogPage compositePage = new TabbedDialogPage("testForm");
              compositePage.addForm(form);
              
              TitledPageApplicationDialog dialog = new TitledPageApplicationDialog(compositePage, getWindowControl()) {
                  protected boolean onFinish() {
                      return true;
                  }
              };
              System.out.println("DIALOG 1 --> " + dialog.getDialog());
              dialog.showDialog();
              System.out.println("DIALOG 2 --> " + dialog.getDialog());
              view.add(dialog.getDialog().getContentPane(),BorderLayout.CENTER);
              return view;
          }
      }
      The Form
      Code:
      import javax.swing.JComponent;
      
      import org.springframework.binding.form.FormModel;
      import org.springframework.richclient.form.AbstractForm;
      import org.springframework.richclient.form.binding.swing.SwingBindingFactory;
      import org.springframework.richclient.form.builder.TableFormBuilder;
      
      public class TestForm extends AbstractForm {
          public TestForm(final FormModel formModel) {
              super(formModel, "testForm");
          }
      
          protected JComponent createFormControl() {
              TableFormBuilder formBuilder = new TableFormBuilder(getBindingFactory());
              SwingBindingFactory bindingFactory = (SwingBindingFactory) getBindingFactory();
              formBuilder.add("name");
              formBuilder.row();
              formBuilder.add("address");
              formBuilder.row();
              formBuilder.add("city");
      
              return formBuilder.getForm();
          }
      }
      messages.properties
      Code:
      ##
      # TEST VIEW
      ##
      testView.label=Test
      # Caption is used for the TOOLBAR!
      testView.caption=Test
      testForm.title=Test Form
      testForm.testForm.title=Test Page
      testForm.name.label=Name
      testForm.address.label=Address
      testForm.name.displayName=the name
      The Validating rule: (add it in your DefaultRulesSource)
      Code:
          private Rules createTestRules() {
              return new Rules(Test.class) {
                  protected void initRules() {
                      add("name", all(
                              new Constraint[] { 
                                      required(), 
                                      maxLength(15), 
                                      regexp("[a-zA-Z -]*", 
                                              "alphabetic") }));
                  }
              };
          }
      the -context.xml Test added to the File Menu
      Code:
          <bean id="showTestViewCommand" class="org.springframework.richclient.command.support.ShowViewCommand">
               <property name="viewDescriptor">
                  <ref bean="testView"/>
               </property>
          </bean>
      
          <bean id="fileMenu" 
      	class="org.springframework.richclient.command.CommandGroupFactoryBean">
      	<property name="members">
         	   <list>
      		<value>showTestViewCommand</value>
         	   </list>
      	</property>
          </bean>
      the -application-context.xml
      Code:
      <bean id="testView"
      	class="org.springframework.richclient.application.support.DefaultViewDescriptor">
      	<property name="viewClass">
      		<value>TestView</value>
      	</property>
      		</property>
      </bean>
      Et voila!

      So the remaining questions are:
      1/ Is this ok???
      2/ Can the ApplicationDialog be modified, say getDialog() to call createDialog() if it is null.
      Or give a way to create it from outside.
      3/ Shall I put this in a wiki page?
      4/ I shall raise a JIRA for modifying the ApplicationDialog after I test a few things.

      Hope this helps!

      Let me know

      best regards

      Benoit

      Comment


      • #4
        ok.. but...

        Hi

        Changing the ApplicationDialog like this:
        Code:
            public JDialog getDialog&#40;&#41; &#123;
                if &#40;!isControlCreated&#40;&#41;&#41; &#123;
                    createDialog&#40;&#41;;
                &#125;
                return dialog;
            &#125;
        
            public Container getDialogContentPane&#40;&#41; &#123;
                if &#40;!isControlCreated&#40;&#41;&#41; &#123;
                    createDialog&#40;&#41;;
                &#125;
                Assert.state&#40;isControlCreated&#40;&#41;, "The wrapped JDialog control could not be created."&#41;;
                return dialog.getContentPane&#40;&#41;;
            &#125;
        and simply calling getDialogContentPane() in my view seems to work.
        Code:
            protected JComponent createControl&#40;&#41; &#123;
                JPanel view = new JPanel&#40;new BorderLayout&#40;&#41;&#41;;              
                
                // create a form and try to add it to the view...
                ValidatingFormModel model = FormModelHelper.createFormModel&#40;new Test&#40;"Benoit","Docklands","London"&#41;&#41;;
                TestForm form = new TestForm&#40;model&#41;;
                
                TabbedDialogPage compositePage = new TabbedDialogPage&#40;"testForm"&#41;;
                compositePage.addForm&#40;form&#41;;
                
                TitledPageApplicationDialog dialog = new TitledPageApplicationDialog&#40;compositePage&#41; &#123;
                    protected boolean onFinish&#40;&#41; &#123;
                        return true;
                    &#125;
                &#125;;
                dialog.setCloseAction&#40;CloseAction.HIDE&#41;;
                view.add&#40;dialog.getDialogContentPane&#40;&#41;,BorderLayout.CENTER&#41;;
                return view;
        But... for some reason an exception is thrown, however it does not stop the GUI to behave as expected with the validating form... The exception is way beyond my Swing skills... so any help would be greatly appreciated!

        The exception is caught by ApplicationLifecycleAdvisor (that is why I did not spot it before...)

        Thanks!

        Code:
        &#91;ERROR,79544,ApplicationLifecycleAdvisor,AWT-EventQueue-0&#93; 1
        java.lang.ArrayIndexOutOfBoundsException&#58; 1
        at java.awt.Container.validateTree&#40;Container.java&#58;1476&#41;
        at java.awt.Container.validateTree&#40;Container.java&#58;1480&#41;
        at java.awt.Container.validateTree&#40;Container.java&#58;1480&#41;
        at java.awt.Container.validate&#40;Container.java&#58;1448&#41;
        at javax.swing.JLayeredPane.addImpl&#40;JLayeredPane.java&#58;205&#41;
        at java.awt.Container.add&#40;Container.java&#58;351&#41;
        at org.springframework.richclient.control.ScrollingDesktopPane.add&#40;ScrollingDesktopPane.java&#58;95&#41;
        at org.springframework.richclient.application.support.DesktopApplicationPage.createPageComponent&#40;DesktopApplicationPage.java&#58;54&#41;
        at org.springframework.richclient.application.support.AbstractApplicationPage.showView&#40;AbstractApplicationPage.java&#58;155&#41;
        at org.springframework.richclient.command.support.ShowViewCommand.doExecuteCommand&#40;ShowViewCommand.java&#58;51&#41;
        at org.springframework.richclient.command.ActionCommand.execute&#40;ActionCommand.java&#58;188&#41;
        at org.springframework.richclient.command.ActionCommand$1.actionPerformed&#40;ActionCommand.java&#58;123&#41;
        at javax.swing.AbstractButton.fireActionPerformed&#40;AbstractButton.java&#58;1849&#41;
        at javax.swing.AbstractButton$Handler.actionPerformed&#40;AbstractButton.java&#58;2169&#41;
        at javax.swing.DefaultButtonModel.fireActionPerformed&#40;DefaultButtonModel.java&#58;420&#41;
        at javax.swing.DefaultButtonModel.setPressed&#40;DefaultButtonModel.java&#58;258&#41;
        at javax.swing.AbstractButton.doClick&#40;AbstractButton.java&#58;302&#41;
        at javax.swing.plaf.basic.BasicMenuItemUI.doClick&#40;BasicMenuItemUI.java&#58;1000&#41;
        at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased&#40;BasicMenuItemUI.java&#58;1041&#41;
        at java.awt.Component.processMouseEvent&#40;Component.java&#58;5488&#41;
        at javax.swing.JComponent.processMouseEvent&#40;JComponent.java&#58;3093&#41;
        at java.awt.Component.processEvent&#40;Component.java&#58;5253&#41;
        at java.awt.Container.processEvent&#40;Container.java&#58;1966&#41;
        at java.awt.Component.dispatchEventImpl&#40;Component.java&#58;3955&#41;
        at java.awt.Container.dispatchEventImpl&#40;Container.java&#58;2024&#41;
        at java.awt.Component.dispatchEvent&#40;Component.java&#58;3803&#41;
        at java.awt.LightweightDispatcher.retargetMouseEvent&#40;Container.java&#58;4212&#41;
        at java.awt.LightweightDispatcher.processMouseEvent&#40;Container.java&#58;3892&#41;
        at java.awt.LightweightDispatcher.dispatchEvent&#40;Container.java&#58;3822&#41;
        at java.awt.Container.dispatchEventImpl&#40;Container.java&#58;2010&#41;
        at java.awt.Window.dispatchEventImpl&#40;Window.java&#58;1766&#41;
        at java.awt.Component.dispatchEvent&#40;Component.java&#58;3803&#41;
        at java.awt.EventQueue.dispatchEvent&#40;EventQueue.java&#58;463&#41;
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy&#40;EventDispatchThread.java&#58;234&#41;
        at java.awt.EventDispatchThread.pumpEventsForHierarchy&#40;EventDispatchThread.java&#58;163&#41;
        at java.awt.EventDispatchThread.pumpEvents&#40;EventDispatchThread.java&#58;157&#41;
        at java.awt.EventDispatchThread.pumpEvents&#40;EventDispatchThread.java&#58;149&#41;
        at java.awt.EventDispatchThread.run&#40;EventDispatchThread.java&#58;110&#41;
        Also how would one "dispose" of a view in the onFinish() method.

        Thanks again!

        Benoit

        Comment


        • #5
          Solution...

          Hi

          I love answering my own question.

          the ApplicationDialog.getDialogContentPane() should do the following:

          Code:
              public Container getDialogContentPane&#40;&#41; &#123;
                  if &#40;!isControlCreated&#40;&#41;&#41; &#123;
                      createDialog&#40;&#41;;
                      dialog.pack&#40;&#41;;
                      onAboutToShow&#40;&#41;;
                      if &#40;getLocation&#40;&#41; != null&#41;
                          dialog.setLocation&#40;getLocation&#40;&#41;&#41;;
                       else
                          dialog.setLocationRelativeTo&#40;parent&#41;;
                  &#125;
                  Assert.state&#40;isControlCreated&#40;&#41;, "The wrapped JDialog control could not be created."&#41;;
                  return dialog.getContentPane&#40;&#41;;
              &#125;
          The "pack()" is critical in order to solve the exception but I guess that the other 2 method calls may also be useful.

          I have raised the following JIRA to suggest the changes to ApplicationDialog:

          http://opensource2.atlassian.com/pro...browse/RCP-193

          I hope that this will be accepted.

          Thanks

          Benoit

          Comment

          Working...
          X