Slick Forums

Discuss the Slick 2D Library
It is currently Sat May 25, 2013 12:11 pm

All times are UTC




Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Fri Aug 17, 2012 4:31 am 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
This isn't specifically TWL related, but thought I'd get some expert developer's opinion on how to design a "window". Basically, only one of these window will exist in the entire game (it'll be hidden when not in use), it'll contain various widgets.

I add it like this:
Code:
WindowSystemSettings wss = new WindowSystemSettings();
root.add(wss);


The class looks like this:
Code:
public class WindowSystemSettings extends ResizableFrame {
   public WindowSystemSettings() {
      setTitle("Settings");
      setTheme("resizableframe-title");

      Button button = new Button("[save]");
      button.setSize(100, 100);
      button.setPosition(100, 100);
      this.add(button);
      this.setSize(100, 100);
   }
}


It just odd to me to be adding everything to the constructor.

What do you guys think? Should it be in it's own class?

A singleton?
Code:
public class WindowSystemSettings extends ResizableFrame {

   private static volatile WindowSystemSettings instance = null;

   public static WindowSystemSettings getInstance(GameContainer gc) {
      if (instance == null) {
         synchronized (TWLMain.class) {
            if (instance == null) {
               instance = new WindowSystemSettings();
            }
         }
      }
      return (instance);
   }

   public WindowSystemSettings() {
      setTitle("Settings");
      setTheme("resizableframe-title");

      Button button = new Button("[save]");
      button.setSize(100, 100);
      button.setPosition(100, 100);
      this.add(button);

      this.setSize(100, 100);
   }
}


I could just hardcode it where I do the "root.add(wss);", but seems like it would be messy.

thoughts?


Top
 Profile  
 
PostPosted: Fri Aug 17, 2012 5:46 am 
Offline
Slick Zombie

Joined: Fri Jan 29, 2010 7:02 pm
Posts: 1173
A few things about singletons:
- you don't need a singleton - I suggest to stay away from static fields at all
- don't use the double-checked locking for the singletons - Java has a much easier way to do that
- remember that TWL code is not thread safe (and OpenGL is basically only single threaded too)

About making your window:
- don't call setSize() or setPosition() outside of layout() *except* for positioning the ResizableFrame itself
- you should probably make another subclass of Widget (or DialogLayout) which will hold your buttons & co and add that to the ResizableFrame (eg don't add your buttons & co directly to the ResizableFrame)
- showing/hiding the window as needed is fine - you can construct it either the first time it is needed or already at startup

_________________
TWL - The Themable Widget Library


Top
 Profile  
 
PostPosted: Fri Aug 17, 2012 6:32 am 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
As always, thanks for the reply Matthias.

MatthiasM wrote:
A few things about singletons:
- you don't need a singleton - I suggest to stay away from static fields at all

There should only be one instance. Shouldn't I try to make sure it's never created twice?

Quote:
- don't use the double-checked locking for the singletons - Java has a much easier way to do that

How is that? I know it's outside the scope of this forum, so understand if you ignore this question :)

Quote:
- remember that TWL code is not thread safe (and OpenGL is basically only single threaded too)

Fair enough ;)


Quote:
About making your window:
- don't call setSize() or setPosition() outside of layout() *except* for positioning the ResizableFrame itself

I don't know if I understand this. Do I do this when I create the ResizableFrame ? [ie. wss.setSize(100,100)].

If I override layout() I get weird behaviors.

Quote:
- you should probably make another subclass of Widget (or DialogLayout) which will hold your buttons & co and add that to the ResizableFrame (eg don't add your buttons & co directly to the ResizableFrame)

like this?

Code:
public class WindowSystemSettings extends ResizableFrame {

   public WindowSystemSettings() {
      setTitle("Settings");
      setTheme("resizableframe-title");
      add(new WindowSystemSettingsWidget());
      this.setVisible(true);
   }
   
   @Override
   public void layout() {
      super.layout();
      // won't resize if uncommented
      //setSize(100,100);
   }

   public class WindowSystemSettingsWidget extends Widget {
      public WindowSystemSettingsWidget() {
         setTheme("");
         Button button = new Button("[save]");
         // Button is really small unless called.
         // button.setSize(100, 100);
         this.add(button);
      }
   }
}


Top
 Profile  
 
PostPosted: Fri Aug 17, 2012 5:58 pm 
Offline
Slick Zombie

Joined: Fri Jan 29, 2010 7:02 pm
Posts: 1173
The layout() method should only modify direct children - nothing else. This is also written in several places already in this forum and in the javadoc of all related methods.

The only exception to this rule is DesktopArea with ResizableFrame children. In this combination you should set the position and the initial size of the ResizableFrame.

_________________
TWL - The Themable Widget Library


Top
 Profile  
 
PostPosted: Fri Aug 17, 2012 6:20 pm 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
Sorry, I still don't understand. In the javadocs for both ResizableFrame and Widget both say for layout() "Called when the layoutInvalid flag is set. The default implementation does nothing. "

If I set button size in layout() the window doesn't act as expected. Where do I set button size? if unset, it's really tiny.

Code:
public class WindowSystemSettings extends ResizableFrame {

   private Button button;

   public WindowSystemSettings() {
      setTitle("Settings");
      setTheme("resizableframe-title");
      add(new WindowSystemSettingsWidget());
      this.setVisible(true);

      // ResizableFrame can set it's own size/position.
      setSize(100, 100);
      setPosition(100, 100);
   }

   @Override
   public void layout() {
      super.layout();
      // Direct child
      button.setSize(50, 20);
   }

   public class WindowSystemSettingsWidget extends Widget {
      public WindowSystemSettingsWidget() {
         setTheme("");
         button = new Button("[save]");
         this.add(button);
      }
   }
}


Top
 Profile  
 
PostPosted: Fri Aug 17, 2012 9:09 pm 
Offline
Slick Zombie

Joined: Fri Jan 29, 2010 7:02 pm
Posts: 1173
You have the layout() method in the wrong class. It must be in WindowSystemSettingsWidget as that is the parent of your button.

_________________
TWL - The Themable Widget Library


Top
 Profile  
 
PostPosted: Sat Aug 18, 2012 12:18 am 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
thanks, that works a lot better. Only other issue is that it works fine till I re size, but when I re size I can make the window smaller than the widgets

here: http://i.imgur.com/Jbg9i.png

How to prevent this?


Top
 Profile  
 
PostPosted: Sat Aug 18, 2012 5:09 am 
Offline
Slick Zombie

Joined: Fri Jan 29, 2010 7:02 pm
Posts: 1173
You need to also override getMinWidth/getMinHeight and the other methods like getPreferredWidth/Height and getMaxWidth/Height for automatic layouts to work.

_________________
TWL - The Themable Widget Library


Top
 Profile  
 
PostPosted: Sat Aug 18, 2012 8:34 pm 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
MatthiasM wrote:
You need to also override getMinWidth/getMinHeight and the other methods like getPreferredWidth/Height and getMaxWidth/Height


Neat! That works, code below. How do I make a non-resizable resizableframe-title frame? I just want the frame-tile, but not resizable. I override the getWidth, etc and that works but still shows the resizable cursor. I'm assuming I need to set/disable resizeHandle some how?

Quote:
for automatic layouts to work.
What's the alternatives to automatic layouts? Using theme settings?



Code:
public class WindowSystemSettings extends ResizableFrame {

   public WindowSystemSettings() {
      setTitle("Settings");
      setTheme("SystemSettings");

      add(new WindowSystemSettingsWidget());
      this.setVisible(true);

      // ResizableFrame can set it's own size/position.
      setSize(0, 0); // equal to pack();
      setPosition(100, 100);

   }

   public class WindowSystemSettingsWidget extends Widget {

      private Button button;

      public WindowSystemSettingsWidget() {
         setTheme("");
         button = new Button("[save]");
         this.add(button);
      }

      @Override
      public int getMinWidth() {
         int minWidth = 0;
         for (int i = 0; i < getNumChildren(); i++) {
            minWidth += getChild(i).getMinWidth();
         }
         return (minWidth);
      }

      @Override
      public int getPreferredWidth() {
         return (getMinWidth());
      }

      @Override
      public int getMaxWidth() {
         return (getMinWidth());
      }

      @Override
      public int getMinHeight() {
         int minHeight = 0;
         for (int i = 0; i < getNumChildren(); i++) {
            minHeight += getChild(i).getMinHeight();
         }
         return (minHeight);
      }

      @Override
      public int getPreferredHeight() {
         return (getMinHeight());
      }

      @Override
      public int getMaxHeight() {
         return (getMinHeight());
      }

      @Override
      public void layout() {
         super.layout();

         for (int i = 0; i < getNumChildren(); i++) {
            getChild(i).adjustSize();
         }

      }

   }

}


Top
 Profile  
 
PostPosted: Sat Aug 18, 2012 10:32 pm 
Offline
Slick Zombie

Joined: Fri Jan 29, 2010 7:02 pm
Posts: 1173
I suggest you take a look at the javadoc / setters of ResizableFrame.

_________________
TWL - The Themable Widget Library


Top
 Profile  
 
PostPosted: Sat Aug 18, 2012 10:56 pm 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
MatthiasM wrote:
I suggest you take a look at the javadoc / setters of ResizableFrame.


ah, ok, it's setResizableAxis(ResizableFrame.ResizableAxis.NONE);

setResizableAxis doesn't have a javadoc with it though.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group