FengGUI XML themes

Hi,



just a quick announcement to let you guys know that we dropped another dev-release yesterday that includes the finally completed theme loading mechanism. You can now describe themes in XML and load them into FengGUI. Checkout the QtCurve theme as an example:



Just do




org.fenggui.FengGUI.setTheme(new XMLTheme("data/themes/QtCurve/QtCurve.xml"));



before you build your GUI.

Have fun!

Johannes

Screenshots are well loved. :wink:

Hehe, I understand  XD



The screenshot below shows FengGUI running with the QtCurve theme. This shot shows mainly widgets in windows, so it is worth mentioning that you can easily use styled widgets without windows as well of course. Also, the screenshot does not show all widgets available in FengGUI (e.g. table, slider, RotatedLabel, etc.).







Johannes

the screenshot below what?  :expressionless:

Nice screenshot! :slight_smile:



Are you guys planning on releasing multiple themes that will be packaged with FengGUI or will it be like Synth where you have to create your own?  :wink:



I do like the QtCurve theme though, very nice.

the screenshot below what?  undecided


Hmm?  :) did I make up my own English grammar again?

Nice screenshot! Smiley


Thanks!

Are you guys planning on releasing multiple themes that will be packaged with FengGUI or will it be like Synth where you have to create your own?


The idea is that we maintain a few example themes that are included in the regular FengGUI package. So QtCurve is already included in the package. For example, we plan to have a cartoon-like style in the future, but I cant say when one of us is going to compose it. :) It is actually my hope that somebody contributes a theme which we can then add to FengGUI.

Johannes
Schabby said:

the screenshot below what?  undecided


Hmm?  :) did I make up my own English grammar again?


No, just ignore him...that's what we do.  :D

Cool, I need to take a look and see how difficult it is to create themes.  We're using FengGUI in Galaxies Beyond for the panel display system (radar, chat, etc.) so I'm very interested in this. :)
Cool, I need to take a look and see how difficult it is to create themes.  We're using FengGUI in Galaxies Beyond for the panel display system (radar, chat, etc.) so I'm very interested in this.


Ah, that's wonderful!

Bascially, there are two ways to define themes. The first way is to subclass org.fenggui.xml.theme.StandardTheme and implement all the abstract methods (there is one for each widget). The theme will be loaded quicker compared to an XML theme because you safe the parsing time. And you are a bit more powerful than with the XML themes, because you setup the appearance and behavior of the widgets directly in Java which means that you can plug-in your own decorators and behavior classes while with the XML theme you can only use those that are regularly shipped with FengGUI. This actually what another project with commercial background is doing.

The second way is through XML. From a technical point of view, loading a XML theme is pretty much the same as extending org.fenggui.xml.theme.StandardTheme because this is what org.fenggui.xml.theme.XMLTheme does (not exactly, but in a way). The schema for each widget is aligned to its Java class, so that all widget elements look similar to this (here I use TextEditor as illustration):

<TextEditor>
<Appearance>
<Margin/>     
<Border/>     
<Padding/>     
<decorators/>
        <switches/>
    </Appearance>
</TextEditor>

So every widget contains an <Appearance>sub-element. This comes from FengGUIs principle to separate behavior and appearance. Consequently, you find all appearance related settings in <Appearance>.

Margin, Padding and Border are spacings that can be used to reserve space around the content area of a widget. It is borrowed from CSS, so you probably know what they are doing.

The <decorators> element ist used as a a list element that contains backgrounds and borders in the order in which they are drawn. All decorators are labeled with a string that denotes in which widget state they are enabled or disabled. So for example a button has the states "default", "mouseHover" and "pressed" (actually there is also "disabled" and "focused" but I omit that here). An example for how one can make use of it follows:



<decorators>
            <PlainBorderlabel="default" all="1">
              <Color green="0.25" red="0.25" blue="0.25" alpha="1.0"/>
            </PlainBorder>
            <PlainBorder label="mouseHover" all="1">
              <Color value="black"/>
            </PlainBorder>
        </decorators>



In this particular example, a black PlainBorder is shown in mouseHover state and a dark gray one in default state.

That's just a brief introduction. I suggest you check out the QtCurve example theme in which we use actually every feature that FengGUI has to offer :) I will see to it to comment QtCurve.xml in the next couple of days, so that you gain more from reading it.

Have fun!!

Johannes

PS: please let me know if you encounter something strange. We want to improve FengGUI and rely on user feedback for that :)
Cool, I need to take a look and see how difficult it is to create themes.  We're using FengGUI in Galaxies Beyond for the panel display system (radar, chat, etc.) so I'm very interested in this. Smiley


@darkfrog: And please please add a sample to the FengIntegration wiki on how to use FengGui with StandardGame and GameStates, will You ?
(because i never got this to work correctly for the Feng GameMenu example til now)

it's one of the cases where game.lock() doesn't work i think because of some texture stuff (at least before mojomonks previous check in's)

I even add the link to the wiki for You darkfrog 
http://www.jmonkeyengine.com/wiki/doku.php?id=integrating_fenggui_with_jme

edit: typos

I'll add that to my mental TODO list, but if a week goes by and no word then bug me about it again.  :stuck_out_tongue:

Toying around with Themes and I'm getting some strange exceptions when I try to use them.  My first criticism would be that it doesn't seem to support just passing it a URL, you either have to pass it a stream or a String (and the stream requires some additional object to be passed with it).  However, in addition to that I'm getting exceptions when I pass an explicit path to it:


Exception in thread "main" org.fenggui.io.ChildConstructionException
   at org.fenggui.io.InputOnlyStream.constructObject(InputOnlyStream.java:81)
   at org.fenggui.io.XMLInputStream.loadChild(XMLInputStream.java:413)
   at org.fenggui.io.XMLInputStream.processChildren(XMLInputStream.java:320)
   at org.fenggui.xml.theme.XMLTheme.loadInit(XMLTheme.java:85)
   at org.fenggui.xml.theme.XMLTheme.load(XMLTheme.java:154)
   at org.fenggui.xml.theme.XMLTheme.<init>(XMLTheme.java:62)
   at org.fenggui.xml.theme.XMLTheme.<init>(XMLTheme.java:55)
   at com.captiveimagination.gb.GalaxiesBeyondClient.<init>(GalaxiesBeyondClient.java:43)
   at com.captiveimagination.gb.GalaxiesBeyondClient.main(GalaxiesBeyondClient.java:113)
Caused by: java.lang.reflect.InvocationTargetException
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
   at org.fenggui.io.InputOnlyStream.constructObject(InputOnlyStream.java:61)
   ... 8 more
Caused by: org.fenggui.io.ChildConstructionException
   at org.fenggui.io.InputOnlyStream.constructObject(InputOnlyStream.java:81)
   at org.fenggui.io.XMLInputStream.loadChild(XMLInputStream.java:413)
   at org.fenggui.io.XMLInputStream.processChild(XMLInputStream.java:254)
   at org.fenggui.border.PixmapBorder.process(PixmapBorder.java:170)
   at org.fenggui.border.PixmapBorder.<init>(PixmapBorder.java:59)
   ... 13 more
Caused by: java.lang.reflect.InvocationTargetException
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
   at org.fenggui.io.InputOnlyStream.constructObject(InputOnlyStream.java:61)
   ... 17 more
Caused by: org.fenggui.io.MissingElementException: Required sub-element not found in <TopLeftPixmap> (expected one of: [PlainBackground|Color|PixmapBorder16|List|SplitContainer|ScrollBar|Table|ProgressBar|Label|Button|CheckBox|RadioButton|RowLayout|PixmapSwitch|TitledBorder|ScrollContainer|Slider|GradientBackground|Pixmap|BorderLayout|PlainBorder|BevelBorder|Canvas|Font|Window|ComboBox|PixmapBackground|MenuBar|FunnyBackground|Container|StaticLayout|FormLayout|Tree|Menu|TextEditor|Display|GridLayout|PixmapBorder])

 [30] <PixmapBorder name="scrollButtonBorder">
 [31]    <TopLeftPixmap width="2" height="2" y="39" x="94">
 [32]       <Texture ref="QtCurve"/>
 [33]    </TopLeftPixmap>
 [34]    <TopEdgePixmap width="1" height="2" y="39" x="96">
 [35]       <Texture ref="QtCurve"/>
 [36]    </TopEdgePixmap>
 [37]    <TopRightPixmap width="2" height="2" y="39" x="97">
 [38]       <Texture ref="QtCurve"/>
 [39]    </TopRightPixmap>
 [40]    <RightEdgePixmap width="2" height="2" y="42" x="97">
 [41]       <Texture ref="QtCurve"/>
 [42]    </RightEdgePixmap>
 [43]    <BottomRightPixmap width="2" height="2" y="45" x="97">
 [44]       <Texture ref="QtCurve"/>
 [45]    </BottomRightPixmap>
 [46]    <BottomEdgePixmap width="1" height="2" y="45" x="96">
 [47]       <Texture ref="QtCurve"/>
 [48]    </BottomEdgePixmap>
 [49]    <BottomLeftPixmap width="2" height="2" y="45" x="94">
 [50]       <Texture ref="QtCurve"/>
 [51]    </BottomLeftPixmap>
 [52]    <LeftEdgePixmap width="2" height="2" y="42" x="94">
 [53]       <Texture ref="QtCurve"/>
 [54]    </LeftEdgePixmap>
 [55] </PixmapBorder>

   at org.fenggui.io.XMLInputStream.processChild(XMLInputStream.java:280)
   at org.fenggui.render.Pixmap.process(Pixmap.java:189)
   at org.fenggui.render.Pixmap.<init>(Pixmap.java:77)
   ... 22 more



This is running from the latest jME from CVS and the latest FengGUI from SVN.  I got a slightly different exception when I tried to run from the most recent build so I was hoping that switching to the latest from SVN would fix it....alas the exception gets more unusual. :o

Hi darkfrog!



I made your URL issue a new item on our board so that we will hopefully implement it soon.



As for the stack trace, the <TopLeftPixmap> seems to be present, so the problem probably lays somewhere else. In any case, the error message is apparently misleading (which is already a bug on itself).



Can you briefly describe in which setting/environment this problem occurs? Maybe you could also send me your XML file which caused the error (assuming that it is not in QtCurve.xml :slight_smile: ).



Thanks! I will try to resolve the error at work tomorrow  :evil:



Johannes

hehe, well that's what's ironic, it is the QtCurve.xml file directly being used in data/themes/QtCurve/QtCurve.xml in the FengGUI project from SVN that is throwing that. :wink:

yipp, that's ironic indeed because it does perfectly work for us  :? Hmm, the PixmapBorder thing is actually the last thing me modified recently, so it might be that the person who wrote this piece of code has an idea.



I just tested the theme loading mechanism in a jME setting and it worked for me… Does this error always occur? even if you just run org.fenggui.example.LWJGLExampleBasis?



If nothing helps, I will try to come up with a minimalistic theme file to test the system from scratch.



Johannes

Hi darkfrog,

please be sure that the fenggui binding is done before you load the theme.



Apparently the theme loader can't load the texture tag (pixmaps.png) without these binding. The

error output comes a little later when the loader try to reference the texture in the

parent tag TopLeftPixmap (<Texture ref="QtCurve"/>).



Anyway, this solved the same problem for me, i hope that helps.

Hogli



  // Grab a display using an LWJGL binding
  Binding binding = new org.fenggui.render.lwjgl.LWJGLBinding();
  disp = new org.fenggui.Display(binding);
  input = new FengJMEInputHandler(disp);
  // Load theme
  try {
   org.fenggui.FengGUI.setTheme(new XMLTheme("data/themes/QtCurve/QtCurve.xml"));
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOStreamException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

Aha, that explains a lot…I assumed it was like setting the look and feel in Swing where it's always best to set it before you display anything. :o



Okay, I'll give that a shot tonight…thanks for the assist.

Hogli, you are genius! I should have thought about that too. I make that another "frequently" asked question on our FAQ page.



hmm, no, I have a better idea… I make FengGUI check whether there is a valid Binding istance before loading a theme.

Or make it able to load a theme before instantiation might be nice as well.  :stuck_out_tongue:

Yeah, but unfortunately there is no way for the theme to talk to OpenGL without a binding (e.g. to upload textures). So the binding is really essential for pretty much everything in FengGUI.

Why don't you assign the XML theme to a queue that will be invoked when the Display is created?  That way it doesn't matter when the XML theme is called, it will wait to occur when the display is created (or if it's already created will invoke immediately).