Skip to main content

NetBeans XmlMultiView

Posted by lordy on February 26, 2006 at 2:09 PM PST

Hi,

because I currently can't find a solution for a bug, and haven't an idea for a module that is interessting to write, I want to share today some lerning I got during the developent of JnlpMultiView.

It is based on XmlMultiView, which enables you to create a visual editor for every XML file. I was real happy when Geertjan add a project sample to his Update Center. I tried it before but without an example it failed. The example is based on xml/multiview/test which you can find in NetBeans sources.

The structur of the example looks like org.netbeans.modules.bookmultiview where you find visual components and dataload things and org.netbeans.modules.bookmultiview.bookmodel which represent the XML file.

Let's beginn with the model. Creating JavaBeans for every elements of the XML DTD with its subelements and attributes shocked me and looks like a stupid effort. You can't imaging how happy I was when I found out that you can generate this beans automagically! The solution for that is schema2beans and it's real simple to use:
* Downlaod schema2beans
* java -cp ./org-netbeans-modules-schema2beans.jar:./schema2beansdev.jar:./s2banttask.jar org.netbeans.modules.schema2beansdev.GenBeans -f jnlp.dtd

After this you have your model, hippie.

The next interessting file is BookToolBarMVElement. In this is the inner class BookView, where you build the structur of your Design View. Let's take us a look at the screenshot of the Design View, I grouped it with colored borders and the class name on the right site for easyer understanding.

BookMultiView.png

Frist thing we see is the rootChildren, which is also frist build in BookView constructor:

   Node bookNode = new BookNode(book);

   Chapter[] chapters = book.getChapter();
   Node[] chapterNode = new Node[chapters.length];
   Children ch = new Children.Array();
   for (int i=0;i < chapters.length;i++) {
      chapterNode[i] = new ChapterNode(chapters[i]);
   }
   ch.add(chapterNode);
   Node chaptersNode = new SectionContainerNode(ch);
   chaptersNode.setDisplayName("Sections");
   rootChildren.add(new Node[]{bookNode,chaptersNode});

Next is BookNode and his view BookPanel:

   addSection(new SectionPanel(this,bookNode,book));

Now another big part, SectionContainer and his children views ChapterPanel.

   SectionContainer chaptersCont = new SectionContainer(this,chaptersNode,"Sections");

   // creatings section panels for Chapters
   SectionPanel[] pan = new SectionPanel[chapters.length];
   for (int i=0;i < chapters.length;i++) {
      pan[i] = new SectionPanel(this, chapterNode[i], chapters[i]);
      chaptersCont.addSection(pan[i]);
   }
   addSection(chaptersCont);

That was it from BookToolBarMVElement. Some of you maybe notifed that we did never call BookPanel or ChapterPanel there, but I highlighted it in the screenshot, right? That's true because we give SectionPanel always the ChapterNode and the Chapter model on his way.
But how does it know which model represents which view?

Here comes PanelFactory into the game:

   public SectionInnerPanel createInnerPanel(Object key) {
      if (key instanceof Book)
         return new BookPanel((SectionView)editor.getContentView(), dObj, (Book)key);
      else
         return new ChapterPanel((SectionView)editor.getContentView(), dObj, (Chapter)key);
   }

The end makes the view. Panels must extend SectionInnerPanel. SectionInnerPanel is an abstract so you must implement abstract methode setValue(), and offwrite endUIChanges() to keep model in sync.

   public void setValue(javax.swing.JComponent source, Object value) {
      if (source==titleTF) {
         book.setTitle((String)value);
      } else if (source==priceTF) {
         book.setPrice((String)value);
      }
   }

   protected void endUIChange() {
      dObj.modelUpdatedFromUI();
   }

setValue gets only called if you add your JTextComponent before with addModifier(), or optimal to addValidatee() if you want to validate the input. If you don't use a JTextComponent in your view, like a JTable or a JCheckBox, you must write your own change listener that calls setValue.

Hope this helps you guys developing NetBeans Modules.