OSDN Git Service

[fixed] emu classes for new stuff...
authorbadlogicgames <badlogicgames@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Tue, 3 Jul 2012 13:38:19 +0000 (13:38 +0000)
committerbadlogicgames <badlogicgames@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Tue, 3 Jul 2012 13:38:19 +0000 (13:38 +0000)
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/Skin.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/TableToolkit.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/JsonWriter.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/ReflectionPool.java [new file with mode: 0644]

diff --git a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/Skin.java b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/Skin.java
new file mode 100644 (file)
index 0000000..b64ae74
--- /dev/null
@@ -0,0 +1,447 @@
+/*******************************************************************************\r
+ * Copyright 2011 See AUTHORS file.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *   http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ ******************************************************************************/\r
+\r
+package com.badlogic.gdx.scenes.scene2d.ui;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.graphics.Color;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.g2d.BitmapFont;\r
+import com.badlogic.gdx.graphics.g2d.NinePatch;\r
+import com.badlogic.gdx.graphics.g2d.Sprite;\r
+import com.badlogic.gdx.graphics.g2d.TextureAtlas;\r
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;\r
+import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasSprite;\r
+import com.badlogic.gdx.graphics.g2d.TextureRegion;\r
+import com.badlogic.gdx.scenes.scene2d.Actor;\r
+import com.badlogic.gdx.scenes.scene2d.utils.Drawable;\r
+import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;\r
+import com.badlogic.gdx.scenes.scene2d.utils.SpriteDrawable;\r
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;\r
+import com.badlogic.gdx.utils.Array;\r
+import com.badlogic.gdx.utils.Disposable;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+import com.badlogic.gdx.utils.Json;\r
+import com.badlogic.gdx.utils.Json.ReadOnlySerializer;\r
+import com.badlogic.gdx.utils.ObjectMap;\r
+import com.badlogic.gdx.utils.ObjectMap.Entry;\r
+import com.badlogic.gdx.utils.SerializationException;\r
+import com.badlogic.gwtref.client.ReflectionCache;\r
+\r
+/** A skin has a {@link TextureAtlas} and stores resources for UI widgets to use (texture regions, ninepatches, fonts, colors,\r
+ * etc). Resources are named and can be looked up by name and type. Skin provides useful conversions, such as allowing access to\r
+ * regions in the atlas as ninepatches, sprites, drawables, etc.\r
+ * <p>\r
+ * Resources can be added to a skin using code, or defined in JSON. Names can be used in JSON to reference already defined\r
+ * resources or regions in the atlas. The JSON format is:\r
+ * \r
+ * <pre>\r
+ * {\r
+ *     className: {\r
+ *             name: value,\r
+ *             ...\r
+ *     },\r
+ *     className: {\r
+ *             name: value,\r
+ *             ...\r
+ *     },\r
+ *     ...\r
+ * }\r
+ * </pre>\r
+ * \r
+ * The class name is the fully qualified Java class name for the type of resource. The name is the name of the resource for that\r
+ * class, and the value is the serialized resource or style.\r
+ * @author Nathan Sweet */\r
+public class Skin implements Disposable {\r
+       ObjectMap<Class, ObjectMap<String, Object>> resources = new ObjectMap();\r
+       TextureAtlas atlas;\r
+\r
+       public Skin (TextureAtlas atlas) {\r
+               this.atlas = atlas;\r
+               add(atlas);\r
+       }\r
+\r
+       public Skin (FileHandle skinFile, TextureAtlas atlas) {\r
+               this.atlas = atlas;\r
+               add(atlas);\r
+               load(skinFile);\r
+       }\r
+\r
+       public Skin (FileHandle skinFile) {\r
+               this.atlas = new TextureAtlas(skinFile.sibling(skinFile.nameWithoutExtension() + ".atlas"));\r
+               add(atlas);\r
+               load(skinFile);\r
+       }\r
+\r
+       public void load (FileHandle skinFile) {\r
+               try {\r
+                       getJsonLoader(skinFile).fromJson(Skin.class, skinFile);\r
+               } catch (SerializationException ex) {\r
+                       throw new SerializationException("Error reading file: " + skinFile, ex);\r
+               }\r
+       }\r
+\r
+       private void add (TextureAtlas atlas) {\r
+               Array<AtlasRegion> regions = atlas.getRegions();\r
+               for (int i = 0, n = regions.size; i < n; i++) {\r
+                       AtlasRegion region = regions.get(i);\r
+                       add(region.name, region, TextureRegion.class);\r
+               }\r
+       }\r
+\r
+       public void add (String name, Object resource) {\r
+               add(name, resource, resource.getClass());\r
+       }\r
+\r
+       public void add (String name, Object resource, Class type) {\r
+               if (name == null) throw new IllegalArgumentException("name cannot be null.");\r
+               if (resource == null) throw new IllegalArgumentException("resource cannot be null.");\r
+               ObjectMap<String, Object> typeResources = resources.get(type);\r
+               if (typeResources == null) {\r
+                       typeResources = new ObjectMap();\r
+                       resources.put(type, typeResources);\r
+               }\r
+               typeResources.put(name, resource);\r
+       }\r
+\r
+       public <T> T get (Class<T> type) {\r
+               return get("default", type);\r
+       }\r
+\r
+       public <T> T get (String name, Class<T> type) {\r
+               if (name == null) throw new IllegalArgumentException("name cannot be null.");\r
+               if (type == null) throw new IllegalArgumentException("type cannot be null.");\r
+\r
+               if (type == Drawable.class) return (T)getDrawable(name);\r
+               if (type == TextureRegion.class) return (T)getRegion(name);\r
+               if (type == NinePatch.class) return (T)getPatch(name);\r
+               if (type == Sprite.class) return (T)getSprite(name);\r
+\r
+               ObjectMap<String, Object> typeResources = resources.get(type);\r
+               if (typeResources == null) throw new GdxRuntimeException("No " + type.getName() + " registered with name: " + name);\r
+               Object resource = typeResources.get(name);\r
+               if (resource == null) throw new GdxRuntimeException("No " + type.getName() + " registered with name: " + name);\r
+               return (T)resource;\r
+       }\r
+\r
+       public <T> T optional (String name, Class<T> type) {\r
+               if (name == null) throw new IllegalArgumentException("name cannot be null.");\r
+               if (type == null) throw new IllegalArgumentException("type cannot be null.");\r
+               ObjectMap<String, Object> typeResources = resources.get(type);\r
+               if (typeResources == null) return null;\r
+               return (T)typeResources.get(name);\r
+       }\r
+\r
+       public boolean has (String name, Class type) {\r
+               ObjectMap<String, Object> typeResources = resources.get(type);\r
+               if (typeResources == null) return false;\r
+               return typeResources.containsKey(name);\r
+       }\r
+\r
+       /** Returns the name to resource mapping for the specified type, or null if no resources of that type exist. */\r
+       public <T> ObjectMap<String, T> getAll (Class<T> type) {\r
+               return (ObjectMap<String, T>)resources.get(type);\r
+       }\r
+\r
+       public Color getColor (String name) {\r
+               return get(name, Color.class);\r
+       }\r
+\r
+       public BitmapFont getFont (String name) {\r
+               return get(name, BitmapFont.class);\r
+       }\r
+\r
+       public TextureRegion getRegion (String name) {\r
+               TextureRegion region = optional(name, TextureRegion.class);\r
+               if (region != null) return region;\r
+\r
+               Texture texture = optional(name, Texture.class);\r
+               if (texture == null) throw new GdxRuntimeException("No TextureRegion or Texture registered with name: " + name);\r
+               region = new TextureRegion(texture);\r
+               add(name, region, Texture.class);\r
+               return region;\r
+       }\r
+\r
+       /** Returns a registered ninepatch. If no ninepatch is found but a region exists with the name, the region is returned as a\r
+        * ninepatch. If the region is an {@link AtlasRegion} then the {@link AtlasRegion#splits} are used. */\r
+       public NinePatch getPatch (String name) {\r
+               NinePatch patch = optional(name, NinePatch.class);\r
+               if (patch != null) return patch;\r
+\r
+               try {\r
+                       TextureRegion region = getRegion(name);\r
+                       if (region instanceof AtlasRegion) {\r
+                               int[] splits = ((AtlasRegion)region).splits;\r
+                               if (splits != null) patch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]);\r
+                       }\r
+                       if (patch == null) patch = new NinePatch(region);\r
+                       add(name, patch, NinePatch.class);\r
+                       return patch;\r
+               } catch (GdxRuntimeException ex) {\r
+                       throw new GdxRuntimeException("No NinePatch, TextureRegion, or Texture registered with name: " + name);\r
+               }\r
+       }\r
+\r
+       public Sprite getSprite (String name) {\r
+               Sprite sprite = optional(name, Sprite.class);\r
+               if (sprite != null) return sprite;\r
+\r
+               try {\r
+                       TextureRegion textureRegion = getRegion(name);\r
+                       if (textureRegion instanceof AtlasRegion) {\r
+                               AtlasRegion region = (AtlasRegion)textureRegion;\r
+                               if (region.rotate || region.packedWidth != region.originalWidth || region.packedHeight != region.originalHeight)\r
+                                       sprite = new AtlasSprite(region);\r
+                       }\r
+                       if (sprite == null) sprite = new Sprite(textureRegion);\r
+                       add(name, sprite, NinePatch.class);\r
+                       return sprite;\r
+               } catch (GdxRuntimeException ex) {\r
+                       throw new GdxRuntimeException("No NinePatch, TextureRegion, or Texture registered with name: " + name);\r
+               }\r
+       }\r
+\r
+       public Drawable getDrawable (String name) {\r
+               Drawable drawable = optional(name, Drawable.class);\r
+               if (drawable != null) return drawable;\r
+\r
+               // Use texture or texture region. If it has splits, use ninepatch. If it has rotation or whitespace stripping, use sprite.\r
+               try {\r
+                       TextureRegion textureRegion = getRegion(name);\r
+                       if (textureRegion instanceof AtlasRegion) {\r
+                               AtlasRegion region = (AtlasRegion)textureRegion;\r
+                               if (region.splits != null)\r
+                                       drawable = new NinePatchDrawable(getPatch(name));\r
+                               else if (region.rotate || region.packedWidth != region.originalWidth || region.packedHeight != region.originalHeight)\r
+                                       drawable = new SpriteDrawable(getSprite(name));\r
+                       }\r
+                       if (drawable == null) drawable = new TextureRegionDrawable(textureRegion);\r
+               } catch (GdxRuntimeException ignored) {\r
+               }\r
+\r
+               // Check for explicit registration of ninepatch or sprite.\r
+               if (drawable == null) {\r
+                       NinePatch patch = optional(name, NinePatch.class);\r
+                       if (patch != null)\r
+                               drawable = new NinePatchDrawable(patch);\r
+                       else {\r
+                               Sprite sprite = optional(name, Sprite.class);\r
+                               if (sprite != null)\r
+                                       drawable = new SpriteDrawable(sprite);\r
+                               else\r
+                                       throw new GdxRuntimeException("No Drawable, NinePatch, TextureRegion, Texture, or Sprite registered with name: "\r
+                                               + name);\r
+                       }\r
+               }\r
+\r
+               add(name, drawable, Drawable.class);\r
+               return drawable;\r
+       }\r
+\r
+       /** Returns the name of the specified style object, or null if it is not in the skin. This compares potentially every style\r
+        * object in the skin of the same type as the specified style, which may be a somewhat expensive operation. */\r
+       public String find (Object resource) {\r
+               if (resource == null) throw new IllegalArgumentException("style cannot be null.");\r
+               ObjectMap<String, Object> typeResources = resources.get(resource.getClass());\r
+               if (typeResources == null) return null;\r
+               return typeResources.findKey(resource, true);\r
+       }\r
+\r
+       public Drawable newDrawable (String name) {\r
+               Drawable drawable = getDrawable(name);\r
+               if (drawable instanceof TextureRegionDrawable) return new TextureRegionDrawable((TextureRegionDrawable)drawable);\r
+               if (drawable instanceof NinePatchDrawable) return new NinePatchDrawable((NinePatchDrawable)drawable);\r
+               if (drawable instanceof SpriteDrawable) return new SpriteDrawable((SpriteDrawable)drawable);\r
+               throw new GdxRuntimeException("Unable to copy, unknown drawable type: " + drawable.getClass());\r
+       }\r
+\r
+       public Drawable newDrawable (String name, Color tint) {\r
+               Drawable drawable = getDrawable(name);\r
+               if (drawable instanceof TextureRegionDrawable) {\r
+                       Sprite sprite = new Sprite(((TextureRegionDrawable)drawable).getRegion());\r
+                       sprite.setColor(tint);\r
+                       return new SpriteDrawable(sprite);\r
+               }\r
+               if (drawable instanceof NinePatchDrawable) {\r
+                       NinePatchDrawable patchDrawable = new NinePatchDrawable((NinePatchDrawable)drawable);\r
+                       patchDrawable.setPatch(new NinePatch(patchDrawable.getPatch(), tint));\r
+                       return patchDrawable;\r
+               }\r
+               if (drawable instanceof SpriteDrawable) {\r
+                       SpriteDrawable spriteDrawable = new SpriteDrawable((SpriteDrawable)drawable);\r
+                       Sprite sprite = new Sprite(spriteDrawable.getSprite());\r
+                       sprite.setColor(tint);\r
+                       spriteDrawable.setSprite(sprite);\r
+                       return spriteDrawable;\r
+               }\r
+               throw new GdxRuntimeException("Unable to copy, unknown drawable type: " + drawable.getClass());\r
+       }\r
+\r
+       /** Sets the style on the actor to disabled or enabled. This is done by appending "-disabled" to the style name when enabled is\r
+        * false, and removing "-disabled" from the style name when enabled is true. A method named "getStyle" is called the actor via\r
+        * reflection and the name of that style is found in the skin. If the actor doesn't have a "getStyle" method or the style was\r
+        * not found in the skin, no exception is thrown and the actor is left unchanged. */\r
+       public void setEnabled (Actor actor, boolean enabled) {\r
+               actor.setTouchable(enabled);\r
+               // Get current style.\r
+               com.badlogic.gwtref.client.Method method = findMethod(actor.getClass(), "getStyle");\r
+               if (method == null) return;\r
+               Object style;\r
+               try {\r
+                       style = method.invoke(actor);\r
+               } catch (Exception ignored) {\r
+                       return;\r
+               }\r
+               // Determine new style.\r
+               String name = find(style);\r
+               if (name == null) return;\r
+               name = name.replace("-disabled", "") + (enabled ? "" : "-disabled");\r
+               style = get(name, style.getClass());\r
+               // Set new style.\r
+               method = findMethod(actor.getClass(), "setStyle");\r
+               if (method == null) return;\r
+               try {\r
+                       method.invoke(actor, style);\r
+               } catch (Exception ignored) {\r
+               }\r
+       }\r
+\r
+       /** Returns the {@link TextureAtlas} that resources in this skin reference. */\r
+       public TextureAtlas getAtlas () {\r
+               return atlas;\r
+       }\r
+\r
+       /** Disposes the {@link TextureAtlas} and all {@link Disposable} resources in the skin. */\r
+       public void dispose () {\r
+               atlas.dispose();\r
+               for (ObjectMap<String, Object> entry : resources.values()) {\r
+                       for (Object resource : entry.values())\r
+                               if (resource instanceof Disposable) ((Disposable)resource).dispose();\r
+               }\r
+       }\r
+\r
+       protected Json getJsonLoader (final FileHandle skinFile) {\r
+               final Skin skin = this;\r
+\r
+               final Json json = new Json() {\r
+                       @Override\r
+                       public <T> T readValue (Class<T> type, Class elementType, Object jsonData) {\r
+                               // If the JSON is a string but the type is not, look up the actual value by name.                               \r
+                               if (jsonData instanceof String && !ReflectionCache.getType(type).isAssignableFrom(ReflectionCache.getType(CharSequence.class))) return get((String)jsonData, type);\r
+                               return super.readValue(type, elementType, jsonData);\r
+                       }\r
+               };\r
+               json.setTypeName(null);\r
+               json.setUsePrototypes(false);\r
+\r
+               json.setSerializer(Skin.class, new ReadOnlySerializer<Skin>() {\r
+                       public Skin read (Json json, Object jsonData, Class ignored) {\r
+                               ObjectMap<String, ObjectMap> typeToValueMap = (ObjectMap)jsonData;\r
+                               for (Entry<String, ObjectMap> typeEntry : typeToValueMap.entries()) {\r
+                                       String className = typeEntry.key;\r
+                                       ObjectMap<String, ObjectMap> valueMap = (ObjectMap)typeEntry.value;\r
+                                       try {\r
+                                               readNamedObjects(json, ReflectionCache.forName(className).getClassOfType(), valueMap);\r
+                                       } catch (ClassNotFoundException ex) {\r
+                                               throw new SerializationException(ex);\r
+                                       }\r
+                               }\r
+                               return skin;\r
+                       }\r
+\r
+                       private void readNamedObjects (Json json, Class type, ObjectMap<String, ObjectMap> valueMap) {\r
+                               Class addType = type == TintedDrawable.class ? Drawable.class : type;\r
+                               for (Entry<String, ObjectMap> valueEntry : valueMap.entries()) {\r
+                                       String name = valueEntry.key;\r
+                                       Object object = json.readValue(type, valueEntry.value);\r
+                                       if (object == null) continue;\r
+                                       try {\r
+                                               add(name, object, addType);\r
+                                       } catch (Exception ex) {\r
+                                               throw new SerializationException("Error reading " + type.getName() + ": " + valueEntry.key, ex);\r
+                                       }\r
+                               }\r
+                       }\r
+               });\r
+\r
+               json.setSerializer(BitmapFont.class, new ReadOnlySerializer<BitmapFont>() {\r
+                       public BitmapFont read (Json json, Object jsonData, Class type) {\r
+                               String path = json.readValue("file", String.class, jsonData);\r
+\r
+                               FileHandle fontFile = skinFile.parent().child(path);\r
+                               if (!fontFile.exists()) fontFile = Gdx.files.internal(path);\r
+                               if (!fontFile.exists()) throw new SerializationException("Font file not found: " + fontFile);\r
+\r
+                               // Use a region with the same name as the font, else use a PNG file in the same directory as the FNT file.\r
+                               String regionName = fontFile.nameWithoutExtension();\r
+                               try {\r
+                                       TextureRegion region = skin.optional(regionName, TextureRegion.class);\r
+                                       if (region != null)\r
+                                               return new BitmapFont(fontFile, region, false);\r
+                                       else {\r
+                                               FileHandle imageFile = fontFile.parent().child(regionName + ".png");\r
+                                               if (imageFile.exists())\r
+                                                       return new BitmapFont(fontFile, imageFile, false);\r
+                                               else\r
+                                                       return new BitmapFont(fontFile, false);\r
+                                       }\r
+                               } catch (RuntimeException ex) {\r
+                                       throw new SerializationException("Error loading bitmap font: " + fontFile, ex);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               json.setSerializer(Color.class, new ReadOnlySerializer<Color>() {\r
+                       public Color read (Json json, Object jsonData, Class type) {\r
+                               if (jsonData instanceof String) return get((String)jsonData, Color.class);\r
+                               ObjectMap map = (ObjectMap)jsonData;\r
+                               float r = json.readValue("r", float.class, 0f, jsonData);\r
+                               float g = json.readValue("g", float.class, 0f, jsonData);\r
+                               float b = json.readValue("b", float.class, 0f, jsonData);\r
+                               float a = json.readValue("a", float.class, 1f, jsonData);\r
+                               return new Color(r, g, b, a);\r
+                       }\r
+               });\r
+\r
+               json.setSerializer(TintedDrawable.class, new ReadOnlySerializer() {\r
+                       public Object read (Json json, Object jsonData, Class type) {\r
+                               String name = json.readValue("name", String.class, jsonData);\r
+                               Color color = json.readValue("color", Color.class, jsonData);\r
+                               return newDrawable(name, color);\r
+                       }\r
+               });\r
+\r
+               return json;\r
+       }\r
+\r
+       static private com.badlogic.gwtref.client.Method findMethod (Class type, String name) {\r
+               com.badlogic.gwtref.client.Method[] methods = ReflectionCache.getType(type).getMethods();\r
+               for (int i = 0, n = methods.length; i < n; i++) {\r
+                       com.badlogic.gwtref.client.Method method = methods[i];\r
+                       if (method.getName().equals(name)) return method;\r
+               }\r
+               return null;\r
+       }\r
+\r
+       /** @author Nathan Sweet */\r
+       static public class TintedDrawable {\r
+               public String name;\r
+               public Color color;\r
+       }\r
+}\r
diff --git a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/TableToolkit.java b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/scenes/scene2d/ui/TableToolkit.java
new file mode 100644 (file)
index 0000000..0d309e6
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************\r
+ * Copyright 2011 See AUTHORS file.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *   http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ ******************************************************************************/\r
+\r
+package com.badlogic.gdx.scenes.scene2d.ui;\r
+\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.math.Rectangle;\r
+import com.badlogic.gdx.scenes.scene2d.Actor;\r
+import com.badlogic.gdx.scenes.scene2d.Group;\r
+import com.badlogic.gdx.scenes.scene2d.utils.Layout;\r
+import com.badlogic.gdx.utils.Array;\r
+import com.badlogic.gwtref.client.ReflectionCache;\r
+import com.esotericsoftware.tablelayout.BaseTableLayout.Debug;\r
+import com.esotericsoftware.tablelayout.Toolkit;\r
+\r
+/** The libgdx implementation of the table layout functionality.\r
+ * @author Nathan Sweet */\r
+class TableToolkit extends Toolkit<Actor, Table, TableLayout> {\r
+       static boolean drawDebug;\r
+\r
+       public void addChild (Actor parent, Actor child) {\r
+               child.remove();\r
+               try {\r
+                       ReflectionCache.getType(parent.getClass()).getMethod("setWidget", Actor.class).invoke(parent, child);\r
+                       return;\r
+               } catch (Exception ignored) {\r
+                       // FIXME this is bad\r
+                       Gdx.app.log("TableToolkit", "Couldn't call setWidget", ignored);\r
+               }\r
+               ((Group)parent).addActor(child);\r
+       }\r
+\r
+       public void removeChild (Actor parent, Actor child) {\r
+               ((Group)parent).removeActor(child);\r
+       }\r
+\r
+       public float getMinWidth (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getMinWidth();\r
+               return actor.getWidth();\r
+       }\r
+\r
+       public float getMinHeight (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getMinHeight();\r
+               return actor.getHeight();\r
+       }\r
+\r
+       public float getPrefWidth (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getPrefWidth();\r
+               return actor.getWidth();\r
+       }\r
+\r
+       public float getPrefHeight (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getPrefHeight();\r
+               return actor.getHeight();\r
+       }\r
+\r
+       public float getMaxWidth (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getMaxWidth();\r
+               return 0;\r
+       }\r
+\r
+       public float getMaxHeight (Actor actor) {\r
+               if (actor instanceof Layout) return ((Layout)actor).getMaxHeight();\r
+               return 0;\r
+       }\r
+\r
+       public float getWidth (Actor widget) {\r
+               return widget.getWidth();\r
+       }\r
+\r
+       public float getHeight (Actor widget) {\r
+               return widget.getHeight();\r
+       }\r
+\r
+       public void clearDebugRectangles (TableLayout layout) {\r
+               if (layout.debugRects != null) layout.debugRects.clear();\r
+       }\r
+\r
+       public void addDebugRectangle (TableLayout layout, Debug type, float x, float y, float w, float h) {\r
+               drawDebug = true;\r
+               if (layout.debugRects == null) layout.debugRects = new Array();\r
+               layout.debugRects.add(new DebugRect(type, x, layout.getTable().getHeight() - y, w, h));\r
+       }\r
+\r
+       static class DebugRect extends Rectangle {\r
+               final Debug type;\r
+\r
+               public DebugRect (Debug type, float x, float y, float width, float height) {\r
+                       super(x, y, width, height);\r
+                       this.type = type;\r
+               }\r
+       }\r
+}\r
diff --git a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/JsonWriter.java b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/JsonWriter.java
new file mode 100644 (file)
index 0000000..b85cd16
--- /dev/null
@@ -0,0 +1,184 @@
+/*******************************************************************************\r
+ * Copyright 2011 See AUTHORS file.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *   http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ ******************************************************************************/\r
+\r
+package com.badlogic.gdx.utils;\r
+\r
+import java.io.IOException;\r
+import java.io.Writer;\r
+import java.util.regex.Pattern;\r
+\r
+/** Builder style API for emitting JSON.\r
+ * @author Nathan Sweet */\r
+public class JsonWriter extends Writer {\r
+       Writer writer;\r
+       private final Array<JsonObject> stack = new Array();\r
+       private JsonObject current;\r
+       private boolean named;\r
+       private OutputType outputType = OutputType.json;\r
+\r
+       public JsonWriter (Writer writer) {\r
+               this.writer = writer;\r
+       }\r
+\r
+       public void setOutputType (OutputType outputType) {\r
+               this.outputType = outputType;\r
+       }\r
+\r
+       public JsonWriter name (String name) throws IOException {\r
+               if (current == null || current.array) throw new IllegalStateException("Current item must be an object.");\r
+               if (!current.needsComma)\r
+                       current.needsComma = true;\r
+               else\r
+                       writer.write(',');\r
+               writer.write(outputType.quoteName(name));\r
+               writer.write(':');\r
+               named = true;\r
+               return this;\r
+       }\r
+\r
+       public JsonWriter object () throws IOException {\r
+               if (current != null) {\r
+                       if (current.array) {\r
+                               if (!current.needsComma)\r
+                                       current.needsComma = true;\r
+                               else\r
+                                       writer.write(',');\r
+                       } else {\r
+                               if (!named && !current.array) throw new IllegalStateException("Name must be set.");\r
+                               named = false;\r
+                       }\r
+               }\r
+               stack.add(current = new JsonObject(false));\r
+               return this;\r
+       }\r
+\r
+       public JsonWriter array () throws IOException {\r
+               if (current != null) {\r
+                       if (current.array) {\r
+                               if (!current.needsComma)\r
+                                       current.needsComma = true;\r
+                               else\r
+                                       writer.write(',');\r
+                       } else {\r
+                               if (!named && !current.array) throw new IllegalStateException("Name must be set.");\r
+                               named = false;\r
+                       }\r
+               }\r
+               stack.add(current = new JsonObject(true));\r
+               return this;\r
+       }\r
+\r
+       public JsonWriter value (Object value) throws IOException {\r
+               if (current != null) {\r
+                       if (current.array) {\r
+                               if (!current.needsComma)\r
+                                       current.needsComma = true;\r
+                               else\r
+                                       writer.write(',');\r
+                       } else {\r
+                               if (!named) throw new IllegalStateException("Name must be set.");\r
+                               named = false;\r
+                       }\r
+               }\r
+               if (value == null || value instanceof Number || value instanceof Boolean) {\r
+                       writer.write(String.valueOf(value));\r
+               } else {\r
+                       writer.write(outputType.quoteValue(value.toString()));\r
+               }\r
+               return this;\r
+       }\r
+\r
+       public JsonWriter object (String name) throws IOException {\r
+               return name(name).object();\r
+       }\r
+\r
+       public JsonWriter array (String name) throws IOException {\r
+               return name(name).array();\r
+       }\r
+\r
+       public JsonWriter set (String name, Object value) throws IOException {\r
+               return name(name).value(value);\r
+       }\r
+\r
+       public JsonWriter pop () throws IOException {\r
+               if (named) throw new IllegalStateException("Expected an object, array, or value since a name was set.");\r
+               stack.pop().close();\r
+               current = stack.size == 0 ? null : stack.peek();\r
+               return this;\r
+       }\r
+\r
+       public void write (char[] cbuf, int off, int len) throws IOException {\r
+               writer.write(cbuf, off, len);\r
+       }\r
+\r
+       public void flush () throws IOException {\r
+               writer.flush();\r
+       }\r
+\r
+       public void close () throws IOException {\r
+               while (stack.size > 0)\r
+                       pop();\r
+               writer.close();\r
+       }\r
+\r
+       private class JsonObject {\r
+               final boolean array;\r
+               boolean needsComma;\r
+\r
+               JsonObject (boolean array) throws IOException {\r
+                       this.array = array;\r
+                       writer.write(array ? '[' : '{');\r
+               }\r
+\r
+               void close () throws IOException {\r
+                       writer.write(array ? ']' : '}');\r
+               }\r
+       }\r
+\r
+       static public enum OutputType {\r
+               /** Normal JSON, with all its quotes. */\r
+               json,\r
+               /** Like JSON, but names are only quoted if necessary. */\r
+               javascript,\r
+               /** Like JSON, but names and values are only quoted if necessary. */\r
+               minimal;\r
+\r
+               // FIXME Avian regex matcher can't do that...\r
+//             static private Pattern javascriptPattern = Pattern.compile("[a-zA-Z_$][a-zA-Z_$0-9]*");\r
+//             static private Pattern minimalPattern = Pattern.compile("[a-zA-Z_$][^:}\\], ]*");\r
+\r
+               public String quoteValue (String value) {\r
+                       value = value.replace("\\", "\\\\");\r
+//                     if (this == OutputType.minimal && !value.equals("true") && !value.equals("false") && !value.equals("null")\r
+//                             && minimalPattern.matcher(value).matches()) return value;\r
+                       return '"' + value.replace("\"", "\\\"") + '"';\r
+               }\r
+\r
+               public String quoteName (String value) {\r
+                       value = value.replace("\\", "\\\\");\r
+//                     switch (this) {\r
+//                     case minimal:\r
+//                             if (minimalPattern.matcher(value).matches()) return value;\r
+//                             return '"' + value.replace("\"", "\\\"") + '"';\r
+//                     case javascript:\r
+//                             if (javascriptPattern.matcher(value).matches()) return value;\r
+//                             return '"' + value.replace("\"", "\\\"") + '"';\r
+//                     default:\r
+                               return '"' + value.replace("\"", "\\\"") + '"';\r
+//                     }\r
+               }\r
+       }\r
+}\r
diff --git a/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/ReflectionPool.java b/backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/emu/com/badlogic/gdx/utils/ReflectionPool.java
new file mode 100644 (file)
index 0000000..983ace5
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************\r
+ * Copyright 2011 See AUTHORS file.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *   http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ ******************************************************************************/
+package com.badlogic.gdx.utils;\r
+\r
+import java.lang.reflect.Constructor;\r
+\r
+import com.badlogic.gwtref.client.ReflectionCache;\r
+import com.badlogic.gwtref.client.Type;\r
+\r
+/** Pool that creates new instances of a type using reflection. The type must have a zero argument constructor.\r
+ * {@link Constructor#setAccessible(boolean)} will be used if the class and/or constructor is not visible.\r
+ * @author Nathan Sweet */\r
+public class ReflectionPool<T> extends Pool<T> {\r
+       private final Class<T> type;\r
+\r
+       public ReflectionPool (Class<T> type) {\r
+               this.type = type;\r
+       }\r
+\r
+       public ReflectionPool (Class<T> type, int initialCapacity, int max) {\r
+               super(initialCapacity, max);\r
+               this.type = type;\r
+       }\r
+\r
+       public ReflectionPool (Class<T> type, int initialCapacity) {\r
+               super(initialCapacity);\r
+               this.type = type;\r
+       }\r
+\r
+       protected T newObject () {\r
+               Type t = ReflectionCache.getType(type);\r
+               try {\r
+                       return (T)t.newInstance();\r
+               } catch (Exception ex) {\r
+                       throw new GdxRuntimeException("Unable to create new instance: " + type.getName(), ex);\r
+               }\r
+       }\r
+}
\ No newline at end of file