OSDN Git Service

fix Manifest
authoryasushiito <yas@pen-chan.jp>
Sat, 25 Jan 2014 02:12:48 +0000 (11:12 +0900)
committeryasushiito <yas@pen-chan.jp>
Sat, 25 Jan 2014 02:12:48 +0000 (11:12 +0900)
58 files changed:
app/assets/javascripts/manifest/work/forms.js.coffee.erb
app/assets/javascripts/manifest/work/models.js.coffee.erb
app/controllers/system_controller.rb
lib/manifest.rb
lib/manifest/controller.rb
lib/manifest/controller/action.rb [new file with mode: 0644]
lib/manifest/controller/action/list.rb [moved from lib/manifest/controller/list.rb with 85% similarity]
lib/manifest/controller/action/show.rb [moved from lib/manifest/controller/show.rb with 97% similarity]
lib/manifest/filer.rb
lib/manifest/filer/caption.rb
lib/manifest/filer/caption/face.rb
lib/manifest/filer/caption/face/face.rb [new file with mode: 0644]
lib/manifest/filer/caption/link.rb
lib/manifest/filer/caption/link/link.rb [new file with mode: 0644]
lib/manifest/filer/date.rb
lib/manifest/filer/date/date.rb [new file with mode: 0644]
lib/manifest/filer/edit.rb
lib/manifest/filer/icon.rb
lib/manifest/filer/icon/icon.rb [new file with mode: 0644]
lib/manifest/filer/summary.rb
lib/manifest/filer/summary/summary.rb
lib/manifest/filer/symbol.rb
lib/manifest/filer/symbol/face.rb
lib/manifest/filer/symbol/face/face.rb [new file with mode: 0644]
lib/manifest/filer/symbol/link.rb
lib/manifest/filer/symbol/link/link.rb [new file with mode: 0644]
lib/manifest/form.rb
lib/manifest/form/field.rb [new file with mode: 0644]
lib/manifest/form/field/field.rb [new file with mode: 0644]
lib/manifest/form/field/helper.rb [new file with mode: 0644]
lib/manifest/form/field/helper/helper.rb [new file with mode: 0644]
lib/manifest/form/field/label.rb [new file with mode: 0644]
lib/manifest/form/field/label/label.rb [new file with mode: 0644]
lib/manifest/form/field/tag.rb [new file with mode: 0644]
lib/manifest/form/field/tag/tag.rb [new file with mode: 0644]
lib/manifest/manifest.rb
lib/manifest/model.rb
lib/manifest/model/association/belongs_to.rb
lib/manifest/model/association/has_many.rb
lib/manifest/model/association/has_one.rb
lib/manifest/model/attribute.rb
lib/manifest/model/list.rb
lib/manifest/profiler.rb
lib/manifest/profiler/association.rb
lib/view/filer/caption.rb [moved from lib/filer/caption.rb with 100% similarity]
lib/view/filer/caption/face.rb [moved from lib/filer/caption/face.rb with 100% similarity]
lib/view/filer/caption/link.rb [moved from lib/filer/caption/link.rb with 100% similarity]
lib/view/filer/date.rb [moved from lib/filer/date.rb with 100% similarity]
lib/view/filer/edit.rb [moved from lib/filer/edit.rb with 100% similarity]
lib/view/filer/filer.rb [moved from lib/filer/filer.rb with 100% similarity]
lib/view/filer/icon.rb [moved from lib/filer/icon.rb with 100% similarity]
lib/view/filer/summary.rb [moved from lib/filer/summary.rb with 100% similarity]
lib/view/filer/symbol.rb [moved from lib/filer/symbol.rb with 100% similarity]
lib/view/filer/symbol/face.rb [moved from lib/filer/symbol/face.rb with 100% similarity]
lib/view/filer/symbol/link.rb [moved from lib/filer/symbol/link.rb with 100% similarity]
lib/view/form/form.rb [new file with mode: 0644]
lib/view/profiler/profiler.rb [moved from lib/profiler/profiler.rb with 100% similarity]
public/manifest.json

index 828dd89..71d45e1 100644 (file)
   },\r
 ]\r
 @forms = {\r
-  Panel: 'panel',\r
-  panel: {\r
-    fields: {\r
-      caption: {\r
-        column: 'caption',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      width: {\r
-        column: 'width',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+  base: {\r
+    panel: {\r
+      fields: {\r
+        caption: {\r
+          args: {\r
+            column: 'caption',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-      },\r
-      height: {\r
-        column: 'height',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
-          }, \r
-        },\r
-        row_break: true, \r
-      },\r
-      border: {\r
-        column: 'border',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        width: {\r
+          args: {\r
+            column: 'width',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
           },\r
         },\r
-      },\r
-      publish: {\r
-        column: 'publish',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'select',\r
+        height: {\r
+          args: {\r
+            column: 'height',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              }, \r
+            },\r
+            row_break: true, \r
+          },\r
         },\r
-        row_break: true,\r
-      },\r
-      id: {\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
+        border: {\r
+          args: {\r
+            column: 'border',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        publish: {\r
+          args: {\r
+            column: 'publish',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-      },\r
-      author_id: {\r
-        column: 'author_id',\r
-        label: {\r
-          type: 'hidden',\r
+        id: {\r
+          args: {\r
+            column: 'id',\r
+            label: {\r
+              type: 'none ',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        author_id: {\r
+          args: {\r
+            column: 'author_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
+      field_names: [\r
+        'caption',\r
+        'width',\r
+        'height',\r
+        'border',\r
+        'publish',\r
+        'id',\r
+        'author_id',\r
+      ]\r
     },\r
-    field_names: [\r
-      'caption',\r
-      'width',\r
-      'height',\r
-      'border',\r
-      'publish',\r
-      'id',\r
-      'author_id',\r
-    ]\r
-  },\r
-  PanelPicture: 'panel_picture',\r
-  panel_picture: {\r
-    fields: {\r
-      caption: {\r
-        column: 'caption',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      x: {\r
-        column: 'x',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+    panel_picture: {\r
+      fields: {\r
+        caption: {\r
+          args: {\r
+            column: 'caption',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-      },\r
-      y: {\r
-        column: 'y',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        x: {\r
+          args: {\r
+            column: 'x',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      width: {\r
-        column: 'width',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        y: {\r
+          args: {\r
+            column: 'y',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-        helpers: {\r
-          size: {\r
-            path: 'panels/size_helper',\r
-            options: {\r
-              class: 'panel_picture_width_tool', \r
+        width: {\r
+          args: {\r
+            column: 'width',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
             },\r
+            helpers: {\r
+              size: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/size_helper',\r
+                  class: 'panel_picture_width_tool', \r
+                },\r
+              },\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      height: {\r
-        column: 'height',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
-          }, \r
-        },\r
-        helpers: {\r
-          size: {\r
-            path: 'panels/size_helper',\r
-            options: {\r
-              class: 'panel_picture_height_tool', \r
+        height: {\r
+          args: {\r
+            column: 'height',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              }, \r
             },\r
+            helpers: {\r
+              size: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/size_helper',\r
+                  class: 'panel_picture_height_tool', \r
+                },\r
+              },\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      link: {\r
-        column: 'link',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      id: {\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      panel_id: {\r
-        column: 'panel_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      picture_id: {\r
-        column: 'picture_id',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+        link: {\r
+          args: {\r
+            column: 'link',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        helpers: {\r
-          popup: {\r
-            path: 'panels/popup_helper',\r
-            source: 'pictures',\r
-            options: {\r
+        id: {\r
+          args: {\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
             },\r
           },\r
         },\r
-      },\r
-      z: {\r
-        column: 'z',\r
-        label: {\r
-          type: 'hidden',\r
+        panel_id: {\r
+          args: {\r
+            column: 'panel_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        picture_id: {\r
+          args: {\r
+            column: 'picture_id',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+            helpers: {\r
+              popup: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/popup_helper',\r
+                  source: 'pictures',\r
+                },\r
+              },\r
+            },\r
+          },\r
         },\r
-      },\r
-      t: {\r
-        column: 't',\r
-        label: {\r
-          type: 'hidden',\r
+        z: {\r
+          args: {\r
+            column: 'z',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        t: {\r
+          args: {\r
+            column: 't',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
+      field_names: [\r
+        'caption',\r
+        'x',\r
+        'y',\r
+        'width',\r
+        'height',\r
+        'link',\r
+        'id',\r
+        'panel_id',\r
+        'picture_id',\r
+        'z',\r
+        't',\r
+      ]\r
     },\r
-    field_names: [\r
-      'caption',\r
-      'x',\r
-      'y',\r
-      'width',\r
-      'height',\r
-      'link',\r
-      'id',\r
-      'panel_id',\r
-      'picture_id',\r
-      'z',\r
-      't',\r
-    ]\r
-  },\r
-  speech_balloon: {\r
-    fields: {\r
-      'speech_balloon.id': {\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.panel_id': {\r
-        column: 'panel_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.speech_balloon_template_id': {\r
-        column: 'speech_balloon_template_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.caption': {\r
-        column: 'caption',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      'speech_balloon.z': {\r
-        column: 'z',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.t': {\r
-        column: 't',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.classname': {\r
-        column: 'classname',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech_balloon.settings': {\r
-        column: 'settings',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'balloon.id': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'balloon.speech_balloon_id': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'speech_balloon_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'balloon.system_picture_id': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'system_picture_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'balloon.r': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'r',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+    speech_balloon: {\r
+      fields: {\r
+        'speech_balloon.id': {\r
+          args: {\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-        helpers: {\r
-          tail_angle: {\r
-            path: 'panels/tail_angle_helper',\r
-            options: {\r
+        'speech_balloon.panel_id': {\r
+          args: {\r
+            column: 'panel_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
             },\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      'balloon.x': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'x',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        'speech_balloon.speech_balloon_template_id': {\r
+          args: {\r
+            column: 'speech_balloon_template_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-      },\r
-      'balloon.y': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'y',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        'speech_balloon.caption': {\r
+          args: {\r
+            column: 'caption',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      'balloon.width': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'width',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        'speech_balloon.z': {\r
+          args: {\r
+            column: 'z',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-      },\r
-      'balloon.height': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'height',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        'speech_balloon.t': {\r
+          args: {\r
+            column: 't',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      'balloon.settings': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'settings',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech.id': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech.speech_balloon_id': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'speech_balloon_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      'speech.x': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'x',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+        'speech_balloon.classname': {\r
+          args: {\r
+            column: 'classname',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.y': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'y',\r
-        label: {\r
-          type: 'hidden',\r
+        'speech_balloon.settings': {\r
+          args: {\r
+            column: 'settings',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        'balloon.id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.width': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'width',\r
-        label: {\r
-          type: 'hidden',\r
+        'balloon.speech_balloon_id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'speech_balloon_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        'balloon.system_picture_id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'system_picture_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.height': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'height',\r
-        label: {\r
-          type: 'hidden',\r
+        'balloon.r': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'r',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+            helpers: {\r
+              tail_angle: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/tail_angle_helper',\r
+                },\r
+              },\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        'balloon.x': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'x',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.writing_format_id': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'writing_format_id',\r
-        label: {\r
+        'balloon.y': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'y',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        field: {\r
-          type: 'select',\r
+        'balloon.width': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'width',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.font_size': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'font_size',\r
-        label: {\r
+        'balloon.height': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'height',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        field: {\r
-          type: 'select',\r
+        'balloon.settings': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'settings',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        row_break: true,\r
-      },\r
-      'speech.text_align': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'text_align',\r
-        label: {\r
+        'speech.id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'select',\r
+        'speech.speech_balloon_id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'speech_balloon_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-      },\r
-      'speech.quotes': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'quotes',\r
-        label: {\r
+        'speech.x': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'x',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'text',\r
-          options: {\r
-            size: 5, \r
+        'speech.y': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'y',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-      },\r
-      'speech.content': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'content',\r
-        label: {\r
-          row_break: true,\r
+        'speech.width': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'width',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'text_area',\r
-          options: {\r
-            size: '45x5', \r
+        'speech.height': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'height',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-      },\r
-      'speech.fore_color': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'fore_color',\r
-        label: {\r
-          row_break: true,\r
+        'speech.writing_format_id': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'writing_format_id',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        'speech.font_size': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'font_size',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        helpers: {\r
-          color: {\r
-            path: 'panels/color_helper',\r
-            options: {\r
+        'speech.text_align': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'text_align',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
             },\r
-            wrapper: 'speech-fore_color-wrap',\r
           },\r
         },\r
-      },\r
-      'speech.settings': {\r
-        model: 'speech',\r
-        part: 'speech',\r
-        column: 'settings',\r
-        label: {\r
-          type: 'hidden',\r
+        'speech.quotes': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'quotes',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        'speech.content': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'content',\r
+            label: {\r
+              row_break: true,\r
+            },\r
+            tag: {\r
+              type: 'text_area',\r
+              args: {\r
+                size: '45x5', \r
+              },\r
+            },\r
+          },\r
         },\r
-      },\r
-    },\r
-  },\r
-  CircleSpeechBalloon: {\r
-    base: 'speech_balloon',\r
-    fields: {\r
-    },\r
-    field_names: [\r
-      'speech_balloon.caption',\r
-      'balloon.r',\r
-      'balloon.x',\r
-      'balloon.y',\r
-      'balloon.width',\r
-      'balloon.height',\r
-      'balloon.id',\r
-      'balloon.speech_balloon_id',\r
-      'balloon.system_picture_id',\r
-      'balloon.settings',\r
-      'speech.writing_format_id',\r
-      'speech.font_size',\r
-      'speech.text_align',\r
-      'speech.quotes',\r
-      'speech.content',\r
-      'speech.fore_color',\r
-      'speech.id',\r
-      'speech.speech_balloon_id',\r
-      'speech.x',\r
-      'speech.y',\r
-      'speech.width',\r
-      'speech.height',\r
-      'speech.settings',\r
-      'speech_balloon.id',\r
-      'speech_balloon.panel_id',\r
-      'speech_balloon.speech_balloon_template_id',\r
-      'speech_balloon.classname',\r
-      'speech_balloon.z',\r
-      'speech_balloon.t',\r
-      'speech_balloon.settings',\r
-    ]\r
-  },\r
-  PlainSpeechBalloon: {\r
-    base: 'speech_balloon',\r
-    fields: {\r
-      'balloon.r': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'r',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+        'speech.fore_color': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'fore_color',\r
+            label: {\r
+              row_break: true,\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+            helpers: {\r
+              color: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/color_helper',\r
+                  wrapper: 'speech-fore_color-wrap',\r
+                },\r
+              },\r
+            },\r
+          },\r
         },\r
-      },\r
-    },\r
-    field_names: [\r
-      'speech_balloon.caption',\r
-      'balloon.r',\r
-      'balloon.x',\r
-      'balloon.y',\r
-      'balloon.width',\r
-      'balloon.height',\r
-      'balloon.id',\r
-      'balloon.speech_balloon_id',\r
-      'balloon.system_picture_id',\r
-      'balloon.settings',\r
-      'speech.writing_format_id',\r
-      'speech.font_size',\r
-      'speech.text_align',\r
-      'speech.quotes',\r
-      'speech.content',\r
-      'speech.fore_color',\r
-      'speech.id',\r
-      'speech.speech_balloon_id',\r
-      'speech.x',\r
-      'speech.y',\r
-      'speech.width',\r
-      'speech.height',\r
-      'speech.settings',\r
-      'speech_balloon.id',\r
-      'speech_balloon.panel_id',\r
-      'speech_balloon.speech_balloon_template_id',\r
-      'speech_balloon.classname',\r
-      'speech_balloon.z',\r
-      'speech_balloon.t',\r
-      'speech_balloon.settings',\r
-    ]\r
-  },\r
-  SquareSpeechBalloon: {\r
-    base: 'speech_balloon',\r
-    fields: {\r
-      'balloon.r': {\r
-        model: 'balloon',\r
-        part: 'balloon',\r
-        column: 'r',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+        'speech.settings': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'speech',\r
+            part: 'speech',\r
+            column: 'settings',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
     },\r
-    field_names: [\r
-      'speech_balloon.caption',\r
-      'balloon.r',\r
-      'balloon.x',\r
-      'balloon.y',\r
-      'balloon.width',\r
-      'balloon.height',\r
-      'balloon.id',\r
-      'balloon.speech_balloon_id',\r
-      'balloon.system_picture_id',\r
-      'balloon.settings',\r
-      'speech.writing_format_id',\r
-      'speech.font_size',\r
-      'speech.text_align',\r
-      'speech.quotes',\r
-      'speech.content',\r
-      'speech.fore_color',\r
-      'speech.id',\r
-      'speech.speech_balloon_id',\r
-      'speech.x',\r
-      'speech.y',\r
-      'speech.width',\r
-      'speech.height',\r
-      'speech.settings',\r
-      'speech_balloon.id',\r
-      'speech_balloon.panel_id',\r
-      'speech_balloon.speech_balloon_template_id',\r
-      'speech_balloon.classname',\r
-      'speech_balloon.z',\r
-      'speech_balloon.t',\r
-      'speech_balloon.settings',\r
-    ]\r
-  },\r
-  GroundPicture: 'ground_picture',\r
-  ground_picture: {\r
-    fields: {\r
-      id: {\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      panel_id: {\r
-        column: 'panel_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      picture_id: {\r
-        column: 'picture_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      caption: {\r
-        column: 'caption',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      repeat: {\r
-        column: 'repeat',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'select',\r
-          options: {\r
-            source: 'magic_number',\r
-            key: 'ground_picture_repeat_items',\r
+    ground_picture: {\r
+      fields: {\r
+        id: {\r
+          args: {\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      x: {\r
-        column: 'x',\r
-        label: {\r
+        panel_id: {\r
+          args: {\r
+            column: 'panel_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        picture_id: {\r
+          args: {\r
+            column: 'picture_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
           },\r
         },\r
-      },\r
-      y: {\r
-        column: 'y',\r
-        label: {\r
+        caption: {\r
+          args: {\r
+            column: 'caption',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        repeat: {\r
+          args: {\r
+            column: 'repeat',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
+              args: {\r
+                source: 'magic_number',\r
+                key: 'ground_picture_repeat_items',\r
+              },\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-        row_break: true,\r
-      },\r
-      z: {\r
-        column: 'z',\r
-        label: {\r
-          type: 'hidden',\r
+        x: {\r
+          args: {\r
+            column: 'x',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        y: {\r
+          args: {\r
+            column: 'y',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-      },\r
-      t: {\r
-        column: 't',\r
-        label: {\r
-          type: 'hidden',\r
+        z: {\r
+          args: {\r
+            column: 'z',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        t: {\r
+          args: {\r
+            column: 't',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
+      field_names: [\r
+        'caption',\r
+        'repeat',\r
+        'x',\r
+        'y',\r
+        'z',\r
+        't',\r
+        'id',\r
+        'panel_id',\r
+        'picture_id',\r
+      ]\r
     },\r
-    field_names: [\r
-      'caption',\r
-      'repeat',\r
-      'x',\r
-      'y',\r
-      'z',\r
-      't',\r
-      'id',\r
-      'panel_id',\r
-      'picture_id',\r
-    ]\r
-  },\r
-  GroundColor: 'ground_color',\r
-  ground_color: {\r
-    fields: {\r
-      id: {\r
-        column: 'id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      panel_id: {\r
-        column: 'panel_id',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
-        },\r
-      },\r
-      caption: {\r
-        column: 'caption',\r
-        label: {\r
-        },\r
-        field: {\r
-          type: 'text',\r
-        },\r
-        row_break: true,\r
-      },\r
-      code: {\r
-        column: 'code',\r
-        label: {\r
-          row_break: true,\r
+    ground_color: {\r
+      fields: {\r
+        id: {\r
+          args: {\r
+            column: 'id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'hidden',\r
+        panel_id: {\r
+          args: {\r
+            column: 'panel_id',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        helpers: {\r
-          color: {\r
-            path: 'panels/color_helper',\r
-            options: {\r
+        caption: {\r
+          args: {\r
+            column: 'caption',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'text',\r
             },\r
-            wrapper: 'ground_color-code-wrap'\r
-          }\r
+            row_break: true,\r
+          },\r
         },\r
-        row_break: true,\r
-      },\r
-      orientation: {\r
-        column: 'orientation',\r
-        label: {\r
+        code: {\r
+          args: {\r
+            column: 'code',\r
+            label: {\r
+              row_break: true,\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+            helpers: {\r
+              color: {\r
+                type: 'size',\r
+                args: {\r
+                  path: 'panels/color_helper',\r
+                  wrapper: 'ground_color-code-wrap'\r
+                },\r
+              }\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        field: {\r
-          type: 'select',\r
+        orientation: {\r
+          args: {\r
+            column: 'orientation',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'select',\r
+            },\r
+            row_break: true,\r
+          },\r
         },\r
-        row_break: true,\r
-      },\r
-      xy: {\r
-        column: 'xy',\r
-        label: {\r
+        xy: {\r
+          args: {\r
+            column: 'xy',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              },\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
+        wh: {\r
+          args: {\r
+            column: 'wh',\r
+            label: {\r
+            },\r
+            tag: {\r
+              type: 'number',\r
+              args: {\r
+                size: 5, \r
+              }\r
+            },\r
+            row_break: true,\r
           },\r
         },\r
-      },\r
-      wh: {\r
-        column: 'wh',\r
-        label: {\r
+        z: {\r
+          args: {\r
+            column: 'z',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        field: {\r
-          type: 'number',\r
-          options: {\r
-            size: 5, \r
-          }\r
+        t: {\r
+          args: {\r
+            column: 't',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
-        row_break: true,\r
       },\r
-      z: {\r
-        column: 'z',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+      field_names: [\r
+        'id',\r
+        'panel_id',\r
+        'caption',\r
+        'code',\r
+        'orientation',\r
+        'xy',\r
+        'wh',\r
+        'z',\r
+        't',\r
+      ]\r
+    }\r
+  },\r
+  extend: {\r
+    CircleSpeechBalloon: {\r
+      base: 'speech_balloon',\r
+      fields: {\r
+      },\r
+      field_names: [\r
+        'speech_balloon.caption',\r
+        'balloon.r',\r
+        'balloon.x',\r
+        'balloon.y',\r
+        'balloon.width',\r
+        'balloon.height',\r
+        'balloon.id',\r
+        'balloon.speech_balloon_id',\r
+        'balloon.system_picture_id',\r
+        'balloon.settings',\r
+        'speech.writing_format_id',\r
+        'speech.font_size',\r
+        'speech.text_align',\r
+        'speech.quotes',\r
+        'speech.content',\r
+        'speech.fore_color',\r
+        'speech.id',\r
+        'speech.speech_balloon_id',\r
+        'speech.x',\r
+        'speech.y',\r
+        'speech.width',\r
+        'speech.height',\r
+        'speech.settings',\r
+        'speech_balloon.id',\r
+        'speech_balloon.panel_id',\r
+        'speech_balloon.speech_balloon_template_id',\r
+        'speech_balloon.classname',\r
+        'speech_balloon.z',\r
+        'speech_balloon.t',\r
+        'speech_balloon.settings',\r
+      ]\r
+    },\r
+    PlainSpeechBalloon: {\r
+      base: 'speech_balloon',\r
+      fields: {\r
+        'balloon.r': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'r',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
-      t: {\r
-        column: 't',\r
-        label: {\r
-          type: 'hidden',\r
-        },\r
-        field: {\r
-          type: 'hidden',\r
+      field_names: [\r
+        'speech_balloon.caption',\r
+        'balloon.r',\r
+        'balloon.x',\r
+        'balloon.y',\r
+        'balloon.width',\r
+        'balloon.height',\r
+        'balloon.id',\r
+        'balloon.speech_balloon_id',\r
+        'balloon.system_picture_id',\r
+        'balloon.settings',\r
+        'speech.writing_format_id',\r
+        'speech.font_size',\r
+        'speech.text_align',\r
+        'speech.quotes',\r
+        'speech.content',\r
+        'speech.fore_color',\r
+        'speech.id',\r
+        'speech.speech_balloon_id',\r
+        'speech.x',\r
+        'speech.y',\r
+        'speech.width',\r
+        'speech.height',\r
+        'speech.settings',\r
+        'speech_balloon.id',\r
+        'speech_balloon.panel_id',\r
+        'speech_balloon.speech_balloon_template_id',\r
+        'speech_balloon.classname',\r
+        'speech_balloon.z',\r
+        'speech_balloon.t',\r
+        'speech_balloon.settings',\r
+      ]\r
+    },\r
+    SquareSpeechBalloon: {\r
+      base: 'speech_balloon',\r
+      fields: {\r
+        'balloon.r': {\r
+          type: 'part',\r
+          args: {\r
+            model: 'balloon',\r
+            part: 'balloon',\r
+            column: 'r',\r
+            label: {\r
+              type: 'none',\r
+            },\r
+            tag: {\r
+              type: 'hidden',\r
+            },\r
+          },\r
         },\r
       },\r
+      field_names: [\r
+        'speech_balloon.caption',\r
+        'balloon.r',\r
+        'balloon.x',\r
+        'balloon.y',\r
+        'balloon.width',\r
+        'balloon.height',\r
+        'balloon.id',\r
+        'balloon.speech_balloon_id',\r
+        'balloon.system_picture_id',\r
+        'balloon.settings',\r
+        'speech.writing_format_id',\r
+        'speech.font_size',\r
+        'speech.text_align',\r
+        'speech.quotes',\r
+        'speech.content',\r
+        'speech.fore_color',\r
+        'speech.id',\r
+        'speech.speech_balloon_id',\r
+        'speech.x',\r
+        'speech.y',\r
+        'speech.width',\r
+        'speech.height',\r
+        'speech.settings',\r
+        'speech_balloon.id',\r
+        'speech_balloon.panel_id',\r
+        'speech_balloon.speech_balloon_template_id',\r
+        'speech_balloon.classname',\r
+        'speech_balloon.z',\r
+        'speech_balloon.t',\r
+        'speech_balloon.settings',\r
+      ]\r
     },\r
-    field_names: [\r
-      'id',\r
-      'panel_id',\r
-      'caption',\r
-      'code',\r
-      'orientation',\r
-      'xy',\r
-      'wh',\r
-      'z',\r
-      't',\r
-    ]\r
   }\r
 }\r
 @repeat_texts = ['repeat', 'repeat-x', 'repeat-y', 'no-repeat']\r
index 2cc7fe4..deb3e56 100644 (file)
       has_many: {\r
         scroll_panels: {\r
           foreign_key: 'scroll_id',\r
-          model: 'scroll_panel',\r
+          model_name: 'scroll_panel',\r
         }, \r
         panels: {\r
           through: 'scroll_panel',\r
           foreign_key: 'scroll_id',\r
-          model: 'panel',\r
+          model_name: 'panel',\r
         }, \r
       },\r
     },\r
       play: {\r
         type: 'play',\r
         args: {\r
-          model: 'scroll_panel',\r
+          model_name: 'scroll_panel',\r
           filter_key: 'scroll_id',\r
         },\r
       },\r
       has_many: {\r
         stories: {\r
           foreign_key: 'comic_id',\r
-          model: 'story',\r
+          model_name: 'story',\r
         }, \r
       },\r
       has_many_through: {\r
       has_many: {\r
         story_sheets: {\r
           foreign_key: 'story_id',\r
-          model: 'story_sheet',\r
+          model_name: 'story_sheet',\r
         }, \r
         sheets: {\r
           through: 'story_sheets',\r
           foreign_key: 'story_id',\r
-          model: 'sheet',\r
+          model_name: 'sheet',\r
         }, \r
       },\r
     },\r
       play: {\r
         type: 'play',\r
         args: {\r
-          model: 'story_sheet',\r
+          model_name: 'story_sheet',\r
           filter_key: 'story_id',\r
         },\r
       },\r
       has_many: {\r
         story_sheets: {\r
           foreign_key: 'story_id',\r
-          model: 'story_sheet',\r
+          model_name: 'story_sheet',\r
         }, \r
         stories: {\r
           through: 'story_sheets',\r
           foreign_key: 'sheet_id',\r
-          model: 'story',\r
+          model_name: 'story',\r
         }, \r
         sheet_panels: {\r
           foreign_key: 'sheet_id',\r
-          model: 'sheet_panel',\r
+          model_name: 'sheet_panel',\r
         }, \r
         panels: {\r
           through: 'sheet_panels',\r
           foreign_key: 'sheet_id',\r
-          model: 'panel',\r
+          model_name: 'panel',\r
         }, \r
       },\r
     },\r
       play: {\r
         type: 'play',\r
         args: {\r
-          model: 'sheet_panel',\r
+          model_name: 'sheet_panel',\r
           filter_key: 'sheet_id',\r
         },\r
       },\r
       has_many: {\r
         scroll_panels: {\r
           foreign_key: 'panel_id',\r
-          model: 'scroll_panel',\r
+          model_name: 'scroll_panel',\r
         }, \r
         scrolls: {\r
           through: 'scroll_panels',\r
           foreign_key: 'panel_id',\r
-          model: 'scroll',\r
+          model_name: 'scroll',\r
         }, \r
         sheet_panels: {\r
           foreign_key: 'panel_id',\r
-          model: 'sheet_panel',\r
+          model_name: 'sheet_panel',\r
         }, \r
         sheets: {\r
           through: 'sheet_panels',\r
           foreign_key: 'panel_id',\r
-          model: 'sheet',\r
+          model_name: 'sheet',\r
         }, \r
         panel_pictures: {\r
           foreign_key: 'panel_id',\r
-          model: 'panel_picture',\r
+          model_name: 'panel_picture',\r
         }, \r
         speech_balloons: {\r
           foreign_key: 'panel_id',\r
-          model: 'speech_balloon',\r
+          model_name: 'speech_balloon',\r
         }, \r
         ground_pictures: {\r
           foreign_key: 'panel_id',\r
-          model: 'ground_picture',\r
+          model_name: 'ground_picture',\r
         }, \r
         ground_colors: {\r
           foreign_key: 'panel_id',\r
-          model: 'ground_color',\r
+          model_name: 'ground_color',\r
         }, \r
       },\r
     },\r
       has_one: {\r
         balloon: {\r
           foreign_key: 'speech_balloon_id',\r
-          model: 'balloon',\r
+          model_name: 'balloon',\r
         }, \r
         speech: {\r
           foreign_key: 'speech_balloon_id',\r
-          model: 'speech',\r
+          model_name: 'speech',\r
         }, \r
       },\r
     },\r
       has_many: {\r
         pictures: {\r
           foreign_key: 'original_picture_id',\r
-          model: 'picture',\r
+          model_name: 'picture',\r
         }, \r
       },\r
       has_one: {\r
         resource_picture: {\r
           foreign_key: 'original_picture_id',\r
-          model: 'resource_picture',\r
+          model_name: 'resource_picture',\r
         }, \r
       },\r
     },\r
       has_many: {\r
         speech_balloons: {\r
           foreign_key: 'speech_balloon_template_id',\r
-          model: 'speech_balloon',\r
+          model_name: 'speech_balloon',\r
         }, \r
         panels: {\r
           through: 'speech_balloons',\r
           foreign_key: 'speech_balloon_template_id',\r
-          model: 'panel',\r
+          model_name: 'panel',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         speeches: {\r
           foreign_key: 'writing_format_id',\r
-          model: 'speech',\r
+          model_name: 'speech',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         licenses: {\r
           foreign_key: 'license_group_id',\r
-          model: 'license',\r
+          model_name: 'license',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         resource_pictures: {\r
           foreign_key: 'license_id',\r
-          model: 'resource_picture',\r
+          model_name: 'resource_picture',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         scrolls: {\r
           foreign_key: 'author_id',\r
-          model: 'scroll',\r
+          model_name: 'scroll',\r
         }, \r
         comics: {\r
           foreign_key: 'author_id',\r
-          model: 'comic',\r
+          model_name: 'comic',\r
         }, \r
         stories: {\r
           foreign_key: 'author_id',\r
-          model: 'story',\r
+          model_name: 'story',\r
         }, \r
         sheets: {\r
           foreign_key: 'author_id',\r
-          model: 'sheet',\r
+          model_name: 'sheet',\r
         }, \r
         panels: {\r
           foreign_key: 'author_id',\r
-          model: 'panel',\r
+          model_name: 'panel',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         resource_pictures: {\r
           foreign_key: 'artist_id',\r
-          model: 'resource_picture',\r
+          model_name: 'resource_picture',\r
         }, \r
       },\r
       has_one: {\r
       has_many: {\r
         balloons: {\r
           foreign_key: 'system_picture_id',\r
-          model: 'balloon',\r
+          model_name: 'balloon',\r
         }, \r
         balloon_templates: {\r
           foreign_key: 'system_picture_id',\r
-          model: 'balloon_template',\r
+          model_name: 'balloon_template',\r
         }, \r
         licenses: {\r
           foreign_key: 'system_picture_id',\r
-          model: 'license',\r
+          model_name: 'license',\r
         }, \r
       },\r
       has_one: {\r
index ed74a00..fe79ea2 100644 (file)
@@ -13,8 +13,8 @@ class SystemController < ApplicationController
   end
   
   def reload_manifest
-    Pettanr::Application.manifest = Pettanr::Manifest.new JSON.parse(open(Rails.root + 'public/manifest.json').read)
-    Pettanr::Application.manifest.init
+    Manifest::load JSON.parse(open(Rails.root + 'public/manifest.json').read)
+    Manifest.manifest.init
     respond_to do |format|
       format.html { redirect_to({:action => :index}) }
     end
index 6aedbd0..1121a97 100644 (file)
@@ -1,10 +1,10 @@
 module Manifest
 end
-  require "manifest/manifest"
-  require "manifest/controller"
-  require "manifest/model"
-  require "manifest/profiler"
-  require "manifest/filer"
-  require "manifest/form"
-  require "manifest/system_resources"
+  require_dependency "manifest/manifest"
+  require_dependency "manifest/controller"
+  require_dependency "manifest/model"
+  require_dependency "manifest/profiler"
+  require_dependency "manifest/filer"
+  require_dependency "manifest/form"
+  require_dependency "manifest/system_resources"
 
index 8377e29..63d8f66 100644 (file)
@@ -1,5 +1,4 @@
-require "manifest/controller/list"
-require "manifest/controller/show"
+require_dependency "manifest/controller/action"
 module Manifest
   class Controller
     include ControllerModule
@@ -13,7 +12,6 @@ module Manifest
     end
     
     attr :manifest, :controller_name, :controller_manifest, :item_name, :actions
-    @@types = {'list' => ActionList, 'show' => ActionShow}
     def initialize manifest, controller_name, controller_manifest
       @manifest = manifest
       @controller_name = controller_name
@@ -31,8 +29,7 @@ module Manifest
       @item_name = @controller_manifest['item_name']
       @actions = {}
       @controller_manifest['actions'].each {|action_name, action_manifest|
-        raise "undefined class for controllers > #{@controller_name} > actions > #{action_name} > type >  #{action_manifest['type']}\n" unless @@types[action_manifest['type']]
-        @actions[action_name] = @@types[action_manifest['type']].new(self, action_name, action_manifest)
+        @actions[action_name] = ActionFactory.factory self, action_name, action_manifest
       }
     end
     
diff --git a/lib/manifest/controller/action.rb b/lib/manifest/controller/action.rb
new file mode 100644 (file)
index 0000000..4261e3e
--- /dev/null
@@ -0,0 +1,21 @@
+require_dependency "manifest/controller/action/list"
+require_dependency "manifest/controller/action/show"
+module Manifest
+  module ControllerModule
+    class ActionFactory
+      include ActionModule
+      @@types = {
+        'list' => ActionList, 'show' => ActionShow
+      }
+      def self.factory controller, action_name, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for controllers > #{controller.controller_name} > action > #{action_name}\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for controllers > #{controller.controller_name} > action > #{action_name} > #{type}\n" unless my_class
+        my_class.new(controller, action_name, my_manifest)
+      end
+      
+    end
+    
+  end
+end
similarity index 85%
rename from lib/manifest/controller/list.rb
rename to lib/manifest/controller/action/list.rb
index 9050a31..3cc2dce 100644 (file)
@@ -1,7 +1,8 @@
 module Manifest
-  module ControllerModule
+  module ActionModule
     class ActionList
-      attr :controller, :action_name, :action_manifest, :item_name, :list_name
+      attr :controller, :action_name, :action_manifest, 
+        :item_name, :list_name
       def initialize controller, action_name, action_manifest
         @controller = controller
         @action_name = action_name
@@ -11,13 +12,13 @@ module Manifest
       end
       
       def set_default
-        @action_manifest['item_name'] ||= self.controller.item_name
         @action_manifest['args'] ||= {}
+        @action_manifest['args']['item_name'] ||= self.controller.item_name
       end
       
       def init
-        @item_name = @action_manifest['item_name']
         @args = @action_manifest['args']
+        @item_name = @args['item_name']
         raise "undefined list_name for controllers > #{self.controller_name} > actions > #{@action_name} > args\n" unless @args['list_name']
         @list_name = @args['list_name']
       end
similarity index 97%
rename from lib/manifest/controller/show.rb
rename to lib/manifest/controller/action/show.rb
index 2b0ac62..ed5a27e 100644 (file)
@@ -1,5 +1,5 @@
 module Manifest
-  module ControllerModule
+  module ActionModule
     class ActionShow
       attr :controller, :action_name, :action_manifest, :item_name
       def initialize controller, action_name, action_manifest
index 93a5685..408a856 100644 (file)
@@ -1,9 +1,9 @@
-require "manifest/filer/symbol"
-require "manifest/filer/caption"
-require "manifest/filer/summary"
-require "manifest/filer/icon"
-require "manifest/filer/date"
-require "manifest/filer/edit"
+require_dependency "manifest/filer/symbol"
+require_dependency "manifest/filer/caption"
+require_dependency "manifest/filer/summary"
+require_dependency "manifest/filer/icon"
+require_dependency "manifest/filer/date"
+require_dependency "manifest/filer/edit"
 module Manifest
   class Filer
     include FilerModule
@@ -34,12 +34,16 @@ module Manifest
     end
     
     def init
-      @symbol = Symbol.manager self, @filer_manifest['symbol']
-      @caption = Caption.manager self, @filer_manifest['caption']
-      @summary = Summary.manager self, @filer_manifest['summary']
-      @icon = Icon.manager self, @filer_manifest['icon']
-      @date = Date.manager self, @filer_manifest['date']
-      @edit = Edit.manager self, @filer_manifest['edit']
+      @symbol = Symbol.new self, @filer_manifest['symbol']
+      @caption = Caption.new self, @filer_manifest['caption']
+      @summary = SummaryFactory.factory self, @filer_manifest['summary']
+      @icon = IconFactory.factory self, @filer_manifest['icon']
+      @date = DateFactory.factory self, @filer_manifest['date']
+      @edit = EditFactory.factory self, @filer_manifest['edit']
+    end
+    
+    def filer_name
+      @item_name
     end
     
     def open item_name, items, operators, paginate
index a2c87a2..e764412 100644 (file)
@@ -1,15 +1,9 @@
-require "manifest/filer/caption/face"
-require "manifest/filer/caption/link"
+require_dependency "manifest/filer/caption/face"
+require_dependency "manifest/filer/caption/link"
 module Manifest
   module FilerModule
     class Caption
       include CaptionModule
-      @@face_types = {
-        'column' => ColumnFace, 'method' => MethodFace, 'none' => NoneFace
-      }
-      @@link_types = {
-        'action' => ActionLink, 'none' => NoneLink, 'url_column' => UrlColumnLink
-      }
       attr :filer, :caption_manifest, 
         :face, :link
       
@@ -30,17 +24,8 @@ module Manifest
       end
       
       def init
-        face_manifest = @caption_manifest['face']
-        face_type = face_manifest['type']
-        face_class = @@face_types[face_type]
-        raise "undefined class for filers > #{self.filer_name} > caption > face > #{face_class}\n" unless face_class
-        @face = face_class.new(self, face_manifest)
-        
-        link_manifest = @caption_manifest['link']
-        link_type = link_manifest['type']
-        link_class = @@link_types[link_type]
-        raise "undefined class for filers > #{self.filer_name} > caption > link > #{link_class}\n" unless link_class
-        @link = link_class.new(self, link_manifest)
+        @face = FaceFactory.factory(self, @caption_manifest['face'])
+        @link = LinkFactory.factory(self, @caption_manifest['link'])
       end
       
       def filer_name
index c9e71ca..026b00f 100644 (file)
@@ -1,56 +1,20 @@
+require_dependency "manifest/filer/caption/face/face"
 module Manifest
   module CaptionModule
-    class BaseFace
-      attr :caption, :face_manifest
-      
-      def initialize caption, face_manifest
-        @caption = caption
-        @face_manifest = face_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-        @face_manifest['args'] ||= {}
-      end
-      
-      def init
-        @args = @face_manifest['args']
-      end
-      
-    end
-    
-    class ColumnFace < BaseFace
-      attr  :name
-      
-      def set_default
-        super
-        @face_manifest['args']['name'] ||= 'caption'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
-    
-    class MethodFace < BaseFace
-      attr  :name
-      
-      def set_default
-        super
-      end
-      
-      def init
-        super
-        raise "undefined name for filers > #{self.caption.filer.filer_name} > caption > face\n" unless @args['name']
-        @name = @args['name']
+    class FaceFactory
+      include FaceModule
+      @@types = {
+        'column' => ColumnFace, 'method' => MethodFace, 'none' => NoneFace
+      }
+      def self.factory caption, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for filers > #{caption.filer_name} > caption > face\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{caption.filer_name} > caption > face > #{type}\n" unless my_class
+        my_class.new(caption, my_manifest)
       end
       
     end
     
-    class NoneFace < BaseFace
-    end
   end
 end
diff --git a/lib/manifest/filer/caption/face/face.rb b/lib/manifest/filer/caption/face/face.rb
new file mode 100644 (file)
index 0000000..47c679f
--- /dev/null
@@ -0,0 +1,58 @@
+module Manifest
+  module CaptionModule
+    module FaceModule
+      class BaseFace
+        attr :caption, :face_manifest
+        
+        def initialize caption, face_manifest
+          @caption = caption
+          @face_manifest = face_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @face_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @face_manifest['args']
+        end
+        
+      end
+      
+      class ColumnFace < BaseFace
+        attr  :name
+        
+        def set_default
+          super
+          @face_manifest['args']['name'] ||= 'caption'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+      class MethodFace < BaseFace
+        attr  :name
+        
+        def set_default
+          super
+        end
+        
+        def init
+          super
+          raise "undefined name for filers > #{self.caption.filer.filer_name} > caption > face\n" unless @args['name']
+          @name = @args['name']
+        end
+        
+      end
+      
+      class NoneFace < BaseFace
+      end
+    end
+  end
+end
index a3b17ec..7c757db 100644 (file)
@@ -1,64 +1,17 @@
+require_dependency "manifest/filer/caption/link/link"
 module Manifest
   module CaptionModule
-    class BaseLink
-      attr :caption, :link_manifest
-      
-      def initialize caption, link_manifest
-        @caption = caption
-        @link_manifest = link_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-        @link_manifest['args'] ||= {}
-      end
-      
-      def init
-        @args = @link_manifest['args']
-      end
-      
-    end
-    
-    class ActionLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-        @link_manifest['args']['name'] ||= 'show'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
-    
-    class NoneLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-      end
-      
-      def init
-        super
-      end
-      
-    end
-    
-    class UrlColumnLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-        @link_manifest['args']['name'] ||= 'url'
-      end
-      
-      def init
-        super
-        @name = @args['name']
+    class LinkFactory
+      include LinkModule
+      @@types = {
+        'action' => ActionLink, 'none' => NoneLink, 'url_column' => UrlColumnLink
+      }
+      def self.factory caption, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for filers > #{caption.filer_name} > caption > link\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{caption.filer_name} > caption > link > #{type}\n" unless my_class
+        my_class.new(caption, my_manifest)
       end
       
     end
diff --git a/lib/manifest/filer/caption/link/link.rb b/lib/manifest/filer/caption/link/link.rb
new file mode 100644 (file)
index 0000000..d2ee004
--- /dev/null
@@ -0,0 +1,69 @@
+module Manifest
+  module CaptionModule
+    module LinkModule
+      class BaseLink
+        attr :caption, :link_manifest
+        
+        def initialize caption, link_manifest
+          @caption = caption
+          @link_manifest = link_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @link_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @link_manifest['args']
+        end
+        
+      end
+      
+      class ActionLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+          @link_manifest['args']['name'] ||= 'show'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+      class NoneLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+        end
+        
+        def init
+          super
+        end
+        
+      end
+      
+      class UrlColumnLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+          @link_manifest['args']['name'] ||= 'url'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+    end
+  end
+end
index 3d2a7bc..494af3a 100644 (file)
@@ -1,32 +1,18 @@
+require_dependency "manifest/filer/date/date"
 module Manifest
   module FilerModule
-    class Date
-      
-      attr :filer, :date_manifest
-      
-      def self.manager filer, my_manifest
-        self.new filer, my_manifest
-      end
-      
-      def initialize filer, date_manifest
-        @filer = filer
-        @date_manifest = date_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-      end
-      
-      def init
-      end
-      
-      def filer_name
-        @filer.item_name
-      end
-      
-      def filer_manifest
-        @filer.filer_manifest
+    class DateFactory
+      include DateModule
+      @@types = {
+        'default' => Base
+      }
+      
+      def self.factory filer, my_manifest
+        type = my_manifest['type'] || 'default'
+        raise "undefined type for filers > #{filer.filer_name} > date\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{filer.filer_name} > date > #{type}\n" unless my_class
+        my_class.new(filer, my_manifest)
       end
       
     end
diff --git a/lib/manifest/filer/date/date.rb b/lib/manifest/filer/date/date.rb
new file mode 100644 (file)
index 0000000..ad8ebf4
--- /dev/null
@@ -0,0 +1,26 @@
+module Manifest
+  module FilerModule
+    module  DateModule
+      class Base
+        attr :filer, :date_manifest
+        
+        def initialize filer, date_manifest
+          @filer = filer
+          @date_manifest = date_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @date_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @date_manifest['args']
+        end
+        
+      end
+      
+    end
+  end
+end
index 79a16be..8278b40 100644 (file)
@@ -1,42 +1,18 @@
-require "manifest/filer/edit/edit"
+require_dependency "manifest/filer/edit/edit"
 module Manifest
   module FilerModule
-    class Edit
+    class EditFactory
       include EditModule
       
       @@types = {
         'default' => Default, 'none' => None, 'template' => Template, 'account' => Account
       }
-      attr :filer, :edit_manifest, 
-        :face, :link
-      
-      def self.manager filer, my_manifest
-        type = my_manifest['type']
+      def self.factory filer, my_manifest
+        type = my_manifest['type'] || 'default'
         raise "undefined type for filers > #{filer.item_name} > edit\n" unless type
-        edit_class = @@types[type]
-        raise "undefined class for filers > #{filer.item_name} > edit > #{type}\n" unless edit_class
-        edit_class.new(filer, my_manifest)
-      end
-      
-      def initialize filer, edit_manifest
-        @filer = filer
-        @edit_manifest = edit_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-      end
-      
-      def init
-      end
-      
-      def filer_name
-        @filer.item_name
-      end
-      
-      def filer_manifest
-        @filer.filer_manifest
+        my_class = @@types[type]
+        raise "undefined class for filers > #{filer.item_name} > edit > #{type}\n" unless my_class
+        my_class.new(filer, my_manifest)
       end
       
     end
index 12e6961..7508f6d 100644 (file)
@@ -1,32 +1,18 @@
+require_dependency "manifest/filer/icon/icon"
 module Manifest
   module FilerModule
-    class Icon
-      
-      attr :filer, :icon_manifest
-      
-      def self.manager filer, my_manifest
-        self.new filer, my_manifest
-      end
-      
-      def initialize filer, icon_manifest
-        @filer = filer
-        @icon_manifest = icon_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-      end
-      
-      def init
-      end
-      
-      def filer_name
-        @filer.item_name
-      end
-      
-      def filer_manifest
-        @filer.filer_manifest
+    class IconFactory
+      include IconModule
+      @@types = {
+        'default' => Base
+      }
+      
+      def self.factory filer, my_manifest
+        type = my_manifest['type'] || 'default'
+        raise "undefined type for filers > #{filer.filer_name} > icon\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{filer.filer_name} > icon > #{type}\n" unless my_class
+        my_class.new(filer, my_manifest)
       end
       
     end
diff --git a/lib/manifest/filer/icon/icon.rb b/lib/manifest/filer/icon/icon.rb
new file mode 100644 (file)
index 0000000..ae69f57
--- /dev/null
@@ -0,0 +1,26 @@
+module Manifest
+  module FilerModule
+    module  IconModule
+      class Base
+        attr :filer, :icon_manifest
+        
+        def initialize filer, icon_manifest
+          @filer = filer
+          @icon_manifest = icon_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @icon_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @icon_manifest['args']
+        end
+        
+      end
+      
+    end
+  end
+end
index a60b54f..945aee6 100644 (file)
@@ -1,41 +1,18 @@
-require "manifest/filer/summary/summary"
+require_dependency "manifest/filer/summary/summary"
 module Manifest
   module FilerModule
-    class Summary
+    class SummaryFactory
       include SummaryModule
       @@types = {
         'none' => None, 'template' => Template
       }
-      attr :filer, :summary_manifest, 
-        :summary
       
-      def self.manager filer, my_manifest
+      def self.factory filer, my_manifest
         type = my_manifest['type']
-        raise "undefined type for filers > #{self.filer_name} > summary\n" unless type
-        summary_class = @@types[type]
-        raise "undefined class for filers > #{self.filer_name} > summary > #{type}\n" unless summary_class
-        summary_class.new(filer, my_manifest)
-      end
-      
-      def initialize filer, summary_manifest
-        @filer = filer
-        @summary_manifest = summary_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-      end
-      
-      def init
-      end
-      
-      def filer_name
-        @filer.item_name
-      end
-      
-      def filer_manifest
-        @filer.filer_manifest
+        raise "undefined type for filers > #{filer.filer_name} > summary\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{filer.filer_name} > summary > #{type}\n" unless my_class
+        my_class.new(filer, my_manifest)
       end
       
     end
index fddd323..9e5a1ae 100644 (file)
@@ -29,7 +29,7 @@ module Manifest
         
         def set_default
           super
-          @summary_manifest['args']['name'] ||= 'symbol'
+          @summary_manifest['args']['name'] ||= 'summary'
         end
         
         def init
index f599dd3..eb21420 100644 (file)
@@ -1,15 +1,9 @@
-require "manifest/filer/symbol/face"
-require "manifest/filer/symbol/link"
+require_dependency "manifest/filer/symbol/face"
+require_dependency "manifest/filer/symbol/link"
 module Manifest
   module FilerModule
     class Symbol 
       include SymbolModule
-      @@face_types = {
-        'image' => ImageFace, 'picture' => PictureFace, 'template' => TemplateFace
-      }
-      @@link_types = {
-        'action' => ActionLink, 'none' => NoneLink, 'url_column' => UrlColumnLink
-      }
       attr :filer, :symbol_manifest, 
         :face, :link
       
@@ -30,17 +24,8 @@ module Manifest
       end
       
       def init
-        face_manifest = @symbol_manifest['face']
-        face_type = face_manifest['type']
-        face_class = @@face_types[face_type]
-        raise "undefined class for filers > #{filer_name} > symbol > face > #{face_class}\n" unless face_class
-        @face = face_class.new(self, face_manifest)
-        
-        link_manifest = @symbol_manifest['link']
-        link_type = link_manifest['type']
-        link_class = @@link_types[link_type]
-        raise "undefined class for filers > #{filer_name} > symbol > link > #{link_class}\n" unless link_class
-        @link = link_class.new(self, link_manifest)
+        @face = FaceFactory.factory(self, @symbol_manifest['face'])
+        @link = LinkFactory.factory(self, @symbol_manifest['link'])
       end
       
       def filer_name
index bf22031..2839667 100644 (file)
@@ -1,68 +1,20 @@
+require_dependency "manifest/filer/symbol/face/face"
 module Manifest
   module SymbolModule
-    class BaseFace
-      attr :symbol, :face_manifest
-      
-      def initialize symbol, face_manifest
-        @symbol = symbol
-        @face_manifest = face_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-        @face_manifest['args'] ||= {}
-      end
-      
-      def init
-        @args = @face_manifest['args']
+    class FaceFactory
+      include FaceModule
+      @@types = {
+        'image' => ImageFace, 'picture' => PictureFace, 'template' => TemplateFace
+      }
+      def self.factory symbol, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for filers > #{symbol.filer_name} > symbol > face\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{symbol.filer_name} > symbol > face > #{type}\n" unless my_class
+        my_class.new(symbol, my_manifest)
       end
       
     end
     
-    class ImageFace < BaseFace
-      attr  :name
-      
-      def set_default
-        super
-        @face_manifest['args']['name'] ||= 'item.png'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
-    
-    class PictureFace < BaseFace
-      attr  :name
-      
-      def set_default
-        super
-        @face_manifest['args']['name'] ||= 'symbol_option'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
-    
-    class TemplateFace < BaseFace
-      attr  :name
-      
-      def set_default
-        super
-        @face_manifest['args']['name'] ||= 'symbol'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
   end
 end
diff --git a/lib/manifest/filer/symbol/face/face.rb b/lib/manifest/filer/symbol/face/face.rb
new file mode 100644 (file)
index 0000000..5bf368c
--- /dev/null
@@ -0,0 +1,70 @@
+module Manifest
+  module SymbolModule
+    module FaceModule
+      class BaseFace
+        attr :symbol, :face_manifest
+        
+        def initialize symbol, face_manifest
+          @symbol = symbol
+          @face_manifest = face_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @face_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @face_manifest['args']
+        end
+        
+      end
+      
+      class ImageFace < BaseFace
+        attr  :name
+        
+        def set_default
+          super
+          @face_manifest['args']['name'] ||= 'item.png'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+      class PictureFace < BaseFace
+        attr  :name
+        
+        def set_default
+          super
+          @face_manifest['args']['name'] ||= 'symbol_option'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+      class TemplateFace < BaseFace
+        attr  :name
+        
+        def set_default
+          super
+          @face_manifest['args']['name'] ||= 'symbol'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+    end
+  end
+end
index 3e051e4..b498923 100644 (file)
@@ -1,64 +1,17 @@
+require_dependency "manifest/filer/symbol/link/link"
 module Manifest
   module SymbolModule
-    class BaseLink
-      attr :symbol, :link_manifest
-      
-      def initialize symbol, link_manifest
-        @symbol = symbol
-        @link_manifest = link_manifest
-        self.set_default
-        self.init
-      end
-      
-      def set_default
-        @link_manifest['args'] ||= {}
-      end
-      
-      def init
-        @args = @link_manifest['args']
-      end
-      
-    end
-    
-    class ActionLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-        @link_manifest['args']['name'] ||= 'show'
-      end
-      
-      def init
-        super
-        @name = @args['name']
-      end
-      
-    end
-    
-    class NoneLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-      end
-      
-      def init
-        super
-      end
-      
-    end
-    
-    class UrlColumnLink < BaseLink
-      attr  :name
-      
-      def set_default
-        super
-        @link_manifest['args']['name'] ||= 'url'
-      end
-      
-      def init
-        super
-        @name = @args['name']
+    class LinkFactory
+      include LinkModule
+      @@types = {
+        'action' => ActionLink, 'none' => NoneLink, 'url_column' => UrlColumnLink
+      }
+      def self.factory symbol, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for filers > #{symbol.filer_name} > symbol > link\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for filers > #{symbol.filer_name} > symbol > link > #{type}\n" unless my_class
+        my_class.new(symbol, my_manifest)
       end
       
     end
diff --git a/lib/manifest/filer/symbol/link/link.rb b/lib/manifest/filer/symbol/link/link.rb
new file mode 100644 (file)
index 0000000..9a57066
--- /dev/null
@@ -0,0 +1,69 @@
+module Manifest
+  module SymbolModule
+    module LinkModule
+      class BaseLink
+        attr :symbol, :link_manifest
+        
+        def initialize symbol, link_manifest
+          @symbol = symbol
+          @link_manifest = link_manifest
+          self.set_default
+          self.init
+        end
+        
+        def set_default
+          @link_manifest['args'] ||= {}
+        end
+        
+        def init
+          @args = @link_manifest['args']
+        end
+        
+      end
+      
+      class ActionLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+          @link_manifest['args']['name'] ||= 'show'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+      class NoneLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+        end
+        
+        def init
+          super
+        end
+        
+      end
+      
+      class UrlColumnLink < BaseLink
+        attr  :name
+        
+        def set_default
+          super
+          @link_manifest['args']['name'] ||= 'url'
+        end
+        
+        def init
+          super
+          @name = @args['name']
+        end
+        
+      end
+      
+    end
+  end
+end
index a220afc..0801d41 100644 (file)
+require_dependency "manifest/form/field"
+module Manifest
   class Form
-    attr :item_name, :conf, :manifest, :base, :fields, :field_names
-    def initialize item_name, conf, manifest
-      @item_name = item_name
-      @conf = conf || {}
+    
+    include FormModule
+    def self.base_manager manifest, my_manifests
+      form = {}
+      base = my_manifests['base'] || {}
+      base.each {|form_name, form_manifest|
+        form[form_name] = Form.new(manifest, form_name, form_manifest)
+      }
+      form
+    end
+    
+    def self.extend_manager manifest, my_manifests
+      form = {}
+      extend = my_manifests['extend'] || {}
+      extend.each {|form_name, form_manifest|
+        form[form_name] = ExtendForm.new(manifest, form_name, form_manifest)
+      }
+      form
+    end
+    
+    attr :form_manifest, :form_name, :manifest, 
+      :fields, :field_names
+    def initialize manifest, form_name, form_manifest
       @manifest = manifest
-      @base = @conf['base']
-      @fields = @conf['fields'] || {}
-      @field_names = @conf['field_names'] || []
+      @form_name = form_name
+      @form_manifest = form_manifest
+      self.set_default
+      self.init
+    end
+    
+    def set_default
+      @form_manifest['fields'] ||= {}
+      @form_manifest['field_names'] ||= []
+    end
+    
+    def init
+      @base = @form_manifest['base']
+      @fields = {}
+      @form_manifest['fields'].each {|field_name, field_manifest|
+        @fields[field_name] = FieldFactory.factory(self, field_name, field_manifest)
+      }
+      @field_names = @form_manifest['field_names']
     end
     
   end
   
-
-module Pettanr
-  class FormManager
-    class Form
-      class Field
-        class Text
-          def initialize conf, field
-            @conf = conf
-            @field = field
-          end
-          
-          def tag_options
-            opt = @field.tag_options.merge(@conf['options'] || {})
-            @field.element.field_tag_attributes(@field.column, @field.tag_mounted, opt)
-          end
-          
-          def render view
-            view.text_field_tag @field.tag_name, @field.tag_value, self.tag_options
-          end
-          
-        end
-        
-        class TextArea < Text
-          def render view
-            view.text_area_tag @field.tag_name, @field.tag_value, self.tag_options
-          end
-          
-        end
-        
-        class Number < Text
-          def render view
-            view.number_field_tag @field.tag_name, @field.tag_value, self.tag_options
-          end
-          
-        end
-        
-        class Hidden < Text
-          def render view
-            view.hidden_field_tag @field.tag_name, @field.tag_value, self.tag_options
-          end
-          
-        end
-        
-        class Select < Text
-          def initialize conf, field
-            super
-            @model = Pettanr::Application::manifest.model(@field.model_name)
-            @source_conf = @model.attributes[@field.column]['source']
-          end
-          
-          def items
-            Pettanr::Application::manifest.select_items[@source_conf['type']][@source_conf['key']]
-          end
-          
-          def render view
-            view.select_tag @field.tag_name, 
-              view.options_for_select(view.t_select_items(self.items), :selected => @field.tag_value.to_s ), self.tag_options
-          end
-          
-        end
-        
-        class Helper
-          attr :field
-          def initialize field, name, conf
-            @conf = conf
-            @field = field
-            @name = name
-          end
-          
-          def wrapper
-            @conf['wrapper']
-          end
-          
-          def path
-            @conf['path']
-          end
-          
-          def options
-            @conf['options']
-          end
-          
-        end
-        
-        attr :part, :column, :type, :mounted, :model_name, :tag_options, :helpers, :form
-        @@type = {
-          'text' => Text, 'text_area' => TextArea, 'number' => Number, 
-          'hidden' => Hidden, 'select' => Select
-        }
-        def initialize form, mounted, conf, manifest
-          @form = form
-          @mounted = mounted
-          @conf = conf
-          @manifest = manifest
-          
-          @model_name = @conf['model'] || @form.model_name
-          @part = @conf['part']
-          @column = @conf['column']
-          @label_conf = @conf['label'] || {}
-          @field_conf = @conf['field']
-          @helper_confs = @conf['helpers'] || {}
-          
-          @tag_options = {'data-model' => @model_name}
-          
-          @model_manifest =  Pettanr::Application::manifest.model(@model_name)
-          model_attribute_conf =  @model_manifest.attributes[self.column] || {}
-          @primary_key = model_attribute_conf['primary_key']
-          
-          @helpers = @helper_confs.map do |helper_name, helper_conf|
-            Helper.new self, helper_name, helper_conf
-          end
-        end
-        
-        def element
-          @element ||= if self.part?
-            @form.element.__send__ self.part
-          else
-            @form.element
-          end
-        end
-        
-        def part?
-          self.part != nil
-        end
-        
-        def ignore_field?
-          @primary_key and self.element.new_record?
-        end
-        
-        def label?
-          @label_conf['type'] == nil or @label_conf['type'] != 'hidden'
-        end
-        
-        def label view
-          view.t 'activerecord.attributes.' + self.model_name + '.' +  self.column
-        end
-        
-        def label_break?
-          @label_conf['row_break'] == true
-        end
-        
-        def tag_name
-          if self.part?
-            @form.model_name + '[' + self.model_name + '_attributes][' + self.column + ']'
-          else
-            @form.model_name + '[' + self.column + ']'
-          end
-        end
-        
-        def tag_value
-          self.element.attributes[self.column]
-        end
-        
-        def tag_mounted
-          self.mounted ? 0 : 1
-        end
-        
-        def field
-          @field ||= @@type[@field_conf['type']].new @field_conf, self
-        end
-        
-        def has_helper?
-          !@helpers.empty?
-        end
-        
-        def row_break?
-          @conf['row_break'] == true
-        end
-        
-      end
-      
-      attr :element, :mounted, :attributes, :fields, :model_name
-      def initialize element, operators, mounted, manifest
-        @element = element
-        @operators = operators
-        @mounted = mounted
-        @manifest = manifest
-        
-        @base = @manifest.base
-        @model_name = @base || element.model_name
-        
-        base_field_confs = if @base
-          base_form = Pettanr::Application::manifest.form(@base)
-          base_form.fields
-        else
-          {}
-        end
-        extend_field_confs = @manifest.fields
-        @field_confs = base_field_confs.merge(extend_field_confs)
-        @fields = @manifest.field_names.map do |field_name|
-          field_conf = @field_confs[field_name]
-          Field.new self, @mounted, field_conf, manifest
-        end
-      end
-      
-      def name
-        @element.form_name
-      end
-      
-      def each_field
-        @fields.each do |field|
-          next if field.ignore_field?
-          yield field
-        end
-      end
-      
-    end
+  class ExtendForm < Form
     
-    attr :form_manifest, :item_name, :manifest, :form_conf
-    def initialize form_manifest
-      @form_manifest = form_manifest
-      @item_name = @form_manifest.item_name
-      @manifest = @form_manifest.manifest
-      @form_conf = @form_manifest.conf
-      
+    attr :base
+    def set_default
+      super
+      raise "undefined base for forms > extend > #{self.form_name}\n" unless @form_manifest['base']
     end
     
-    def open element, operators, mounted
-      Form.new element, operators, mounted, @form_manifest
+    def init
+      super
+      @base = @form_manifest['base']
+      @base_form = @manifest.forms[@base]
+      raise "undefined base form for forms > extend > #{self.form_name}\n" unless @base_form
+      @fields.merge! @base_form.fields
     end
     
   end
+  
 end
 
diff --git a/lib/manifest/form/field.rb b/lib/manifest/form/field.rb
new file mode 100644 (file)
index 0000000..cb61f93
--- /dev/null
@@ -0,0 +1,20 @@
+require_dependency "manifest/form/field/field"
+module Manifest
+  module FormModule
+    class FieldFactory
+      include FieldModule
+      @@types = {
+        'element' => ElementField, 'part' => PartField
+      }
+      def self.factory form, field_name, my_manifest
+        type = my_manifest['type'] || 'element'
+        raise "undefined type for forms > #{form.form_name} > fields > #{field_name}\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for forms > #{form.form_name} > fields > #{field_name} > #{type}\n" unless my_class
+        my_class.new(form, field_name, my_manifest)
+      end
+      
+    end
+    
+  end
+end
diff --git a/lib/manifest/form/field/field.rb b/lib/manifest/form/field/field.rb
new file mode 100644 (file)
index 0000000..97ae78b
--- /dev/null
@@ -0,0 +1,77 @@
+require_dependency "manifest/form/field/tag"
+require_dependency "manifest/form/field/label"
+require_dependency "manifest/form/field/helper"
+module Manifest
+  module FormModule
+    class Field
+      include FieldModule
+      attr :form, :field_name, :field_manifest, 
+        :model_name, :column_name, :label, :tag, :helper, :row_break
+      
+      def initialize form, field_name, field_manifest
+        @form = form
+        @field_name = field_name
+        @field_manifest = field_manifest
+        self.set_default
+        self.init
+      end
+      
+      def set_default
+        @field_manifest['args'] ||= {}
+        n = self.field_name.split '.'
+        if n.size > 1
+          @field_manifest['args']['model_name'] ||= n[0]
+          @field_manifest['args']['column_name'] ||= n[1]
+        else
+          @field_manifest['args']['model_name'] ||= self.form.form_name
+          @field_manifest['args']['column_name'] ||= self.field_name
+        end
+        @field_manifest['args']['label'] ||= {}
+        @field_manifest['args']['tag'] ||= {}
+        @field_manifest['args']['helper'] ||= {}
+        @field_manifest['args']['row_break'] ||= true
+      end
+      
+      def init
+        @args = @field_manifest['args']
+        @model_name = @args['model_name']
+        @column_name = @args['column_name']
+        @label = LabelFactory.factory(self, @args['label'])
+        @field = TagFactory.factory(self, @args['tag'])
+        @helper = HelperFactory.factory(self, @args['helper'])
+        @row_break = @args['row_break']
+      end
+      
+      def form_name
+        @form.form_name
+      end
+      
+      def filer_manifest
+        @form.form_manifest
+      end
+      
+    end
+    
+    class ElementField < Field
+    end
+    
+    class PartField < Field
+      attr :part
+      
+      def set_default
+      super
+        @field_manifest['model_name'] ||= ''
+        @field_manifest['column_name'] ||= ''
+        @field_manifest['part'] ||= ''
+      end
+      
+      def init
+        @model_name = @field_manifest['model_name']
+        @column_name = @field_manifest['column_name']
+        @part = @field_manifest['part']
+      end
+      
+    end
+    
+  end
+end
diff --git a/lib/manifest/form/field/helper.rb b/lib/manifest/form/field/helper.rb
new file mode 100644 (file)
index 0000000..d7255d9
--- /dev/null
@@ -0,0 +1,22 @@
+require_dependency "manifest/form/field/helper/helper"
+module Manifest
+  module FormModule
+    module FieldModule
+      class HelperFactory
+        include HelperModule
+        @@types = {
+          'default' => Default, 'none' => None
+        }
+        def self.factory field, my_manifest
+          type = my_manifest['type'] || 'none'
+          raise "undefined type for forms > #{field.form_name} > fields > #{field.field_name} > helper\n" unless type
+          my_class = @@types[type]
+          raise "undefined class for forms > #{field.form_name} > fields > #{field.field_name} > helper > #{type}\n" unless my_class
+          my_class.new(field, my_manifest)
+        end
+        
+      end
+      
+    end
+  end
+end
diff --git a/lib/manifest/form/field/helper/helper.rb b/lib/manifest/form/field/helper/helper.rb
new file mode 100644 (file)
index 0000000..8a11551
--- /dev/null
@@ -0,0 +1,34 @@
+module Manifest
+  module FormModule
+    module FieldModule
+      module HelperModule
+        class Base
+          attr :field, :helper_manifest
+          
+          def initialize field, helper_manifest
+            @field = field
+            @helper_manifest = helper_manifest
+            self.set_default
+            self.init
+          end
+          
+          def set_default
+            @helper_manifest['args'] ||= {}
+          end
+          
+          def init
+            @args = @helper_manifest['args']
+          end
+          
+        end
+        
+        class Default < Base
+        end
+        
+        class None < Base
+        end
+        
+      end
+    end
+  end
+end
diff --git a/lib/manifest/form/field/label.rb b/lib/manifest/form/field/label.rb
new file mode 100644 (file)
index 0000000..278c553
--- /dev/null
@@ -0,0 +1,22 @@
+require_dependency "manifest/form/field/label/label"
+module Manifest
+  module FormModule
+    module FieldModule
+      class LabelFactory
+        include LabelModule
+        @@types = {
+          'default' => Default, 'none' => None
+        }
+        def self.factory field, my_manifest
+          type = my_manifest['type'] || 'default'
+          raise "undefined type for forms > #{field.form_name} > fields > #{field.field_name} > label\n" unless type
+          my_class = @@types[type]
+          raise "undefined class for forms > #{field.form_name} > fields > #{field.field_name} > label > #{type}\n" unless my_class
+          my_class.new(field, my_manifest)
+        end
+        
+      end
+      
+    end
+  end
+end
diff --git a/lib/manifest/form/field/label/label.rb b/lib/manifest/form/field/label/label.rb
new file mode 100644 (file)
index 0000000..fff2f02
--- /dev/null
@@ -0,0 +1,34 @@
+module Manifest
+  module FormModule
+    module FieldModule
+      module LabelModule
+        class Base
+          attr :field, :label_manifest
+          
+          def initialize field, label_manifest
+            @field = field
+            @label_manifest = label_manifest
+            self.set_default
+            self.init
+          end
+          
+          def set_default
+            @label_manifest['args'] ||= {}
+          end
+          
+          def init
+            @args = @label_manifest['args']
+          end
+          
+        end
+        
+        class Default < Base
+        end
+        
+        class None < Base
+        end
+        
+      end
+    end
+  end
+end
diff --git a/lib/manifest/form/field/tag.rb b/lib/manifest/form/field/tag.rb
new file mode 100644 (file)
index 0000000..f699e9b
--- /dev/null
@@ -0,0 +1,23 @@
+require_dependency "manifest/form/field/tag/tag"
+module Manifest
+  module FormModule
+    module FieldModule
+      class TagFactory
+        include TagModule
+        @@types = {
+          'text' => TextTag, 'number' => NumberTag, 'text_area' => TextAreaTag, 
+          'select' => SelectTag, 'hidden' => HiddenTag
+        }
+        def self.factory field, my_manifest
+          type = my_manifest['type']
+          raise "undefined type for forms > #{field.form_name} > fields > #{field.field_name} > tag\n" unless type
+          my_class = @@types[type]
+          raise "undefined class for forms > #{field.form_name} > fields > #{field.field_name} > tag > #{type}\n" unless my_class
+          my_class.new(field, my_manifest)
+        end
+        
+      end
+      
+    end
+  end
+end
diff --git a/lib/manifest/form/field/tag/tag.rb b/lib/manifest/form/field/tag/tag.rb
new file mode 100644 (file)
index 0000000..ea81ef2
--- /dev/null
@@ -0,0 +1,43 @@
+module Manifest
+  module FormModule
+    module FieldModule
+      module TagModule
+        class Base
+          attr :field, :tag_manifest
+          
+          def initialize field, tag_manifest
+            @field = field
+            @tag_manifest = tag_manifest
+            self.set_default
+            self.init
+          end
+          
+          def set_default
+            @tag_manifest['args'] ||= {}
+          end
+          
+          def init
+            @args = @tag_manifest['args']
+          end
+          
+        end
+        
+        class TextTag < Base
+        end
+        
+        class NumberTag < Base
+        end
+        
+        class TextAreaTag < Base
+        end
+        
+        class SelectTag < Base
+        end
+        
+        class HiddenTag < Base
+        end
+        
+      end
+    end
+  end
+end
index 47e84f3..e12d5c0 100644 (file)
@@ -21,7 +21,8 @@ module Manifest
       @locals = @manifest['locals']
       @filers = Filer.manager(self, @locals['filers'])
       @profilers = Profiler.manager(self, @locals['profilers'])
-      @forms = {}
+      @forms = Form.base_manager(self, @locals['forms'])
+      @forms.merge(Form.extend_manager(self, @locals['forms']))
       select_items_loader
       add_action
     end
index 4ba9c42..30748c2 100644 (file)
@@ -1,11 +1,10 @@
-require "manifest/model/attribute"
-require "manifest/model/association"
-require "manifest/model/list"
+require_dependency "manifest/model/attribute"
+require_dependency "manifest/model/association"
+require_dependency "manifest/model/list"
 
 module Manifest
   class Model
     include ModelModule
-    include ListModule
     
     def self.manager manifest, my_manifests
       my_manifests.map {|model_name, model_manifest|
@@ -13,12 +12,6 @@ module Manifest
       }
     end
     
-    @@types = {
-      'public' => PublicList, 'private' => PrivateList, 'system_resource' => SystemResourceList,
-      'has_many' => HasManyList, 'has_many_through' => HasManyThroughList, 'filter' => FilterList, 
-      'through_filter' => ThroughFilterList, 'element_filter' => ElementFilterList, 
-      'play' => PlayList
-    }
     attr :model_name, :model_manifest
     def initialize manifest, model_name, model_manifest
       @manifest = manifest
@@ -37,7 +30,6 @@ module Manifest
     def init
       @attributes = {}
       @model_manifest['attributes'].each {|attribute_name, attribute_manifest|
-        raise "undefined type for models > #{@model_name} > attributes > #{attribute_name}\n" unless attribute_manifest['type']
         @attributes[attribute_name] = Attribute.new(self, attribute_name, attribute_manifest)
       }
       @associations = {}
@@ -46,11 +38,7 @@ module Manifest
       }
       @lists = {}
       @model_manifest['lists'].each {|list_name, list_manifest|
-        type = list_manifest['type']
-        raise "undefined type for models > #{@model_name} > lists > #{list_name}\n" unless type
-        list = @@types[type]
-        raise "undefined class for models > #{@model_name} > actions > #{list_name} > type >  #{type}\n" unless list
-        @lists[list_name] = list.new(self, list_name, list_manifest)
+        @lists[list_name] = ListFactory.factory(self, list_name, list_manifest)
       }
     end
     
index ba459b7..e01eae1 100644 (file)
@@ -3,7 +3,7 @@ module Manifest
     module AssociationModule
       class BelongsTo
         attr :association, :belongs_to_name, :belongs_to_manifest, 
-          :id_column
+          :id_column, :model_name
         def initialize association, belongs_to_name, belongs_to_manifest
           @association = association
           @belongs_to_name = belongs_to_name
@@ -13,10 +13,12 @@ module Manifest
         end
         
         def set_default
+          @belongs_to_manifest['model_name'] ||= @belongs_to_name
           @belongs_to_manifest['id_column'] ||= @belongs_to_name + '_id' 
         end
         
         def init
+          @model_name = @belongs_to_manifest['model_name']
           @id_column = @belongs_to_manifest['id_column']
         end
         
index 5595248..1fddab9 100644 (file)
@@ -3,7 +3,7 @@ module Manifest
     module AssociationModule
       class HasMany
         attr :association, :has_many_name, :has_many_manifest, 
-          :model, :foreign_key, :through
+          :model_name, :foreign_key, :through
         def initialize association, has_many_name, has_many_manifest
           @association = association
           @has_many_name = has_many_name
@@ -13,12 +13,12 @@ module Manifest
         end
         
         def set_default
-          @has_many_manifest['model'] ||= @has_many_name.singularize
+          @has_many_manifest['model_name'] ||= @has_many_name.singularize
         end
         
         def init
-          @model = @has_many_manifest['model']
-          raise "undefined foreign_key for models > #{@association.model.model_name} > associations > has_many > #{@association.association_name}\n" unless @has_many_manifest['foreign_key']
+          @model_name = @has_many_manifest['model_name']
+          raise "undefined foreign_key for models > #{@association.model.model_name} > associations > has_many > #{@has_many_name}\n" unless @has_many_manifest['foreign_key']
           @foreign_key = @has_many_manifest['foreign_key']
           @through = @has_many_manifest['through']
         end
index 9f1efb6..6f4e874 100644 (file)
@@ -3,7 +3,7 @@ module Manifest
     module AssociationModule
       class HasOne
         attr :association, :has_one_name, :has_one_manifest, 
-          :model, :foreign_key
+          :model_name, :foreign_key
         def initialize association, has_one_name, has_one_manifest
           @association = association
           @has_one_name = has_one_name
@@ -13,12 +13,12 @@ module Manifest
         end
         
         def set_default
-          @has_one_manifest['model'] ||= @has_one_name
+          @has_one_manifest['model_name'] ||= @has_one_name
         end
         
         def init
-          @model = @has_one_manifest['model']
-          raise "undefined foreign_key for models > #{@association.model.model_name} > associations > has_one > #{@association.association_name}\n" unless @has_one_manifest['foreign_key']
+          @model_name = @has_one_manifest['model_name']
+          raise "undefined foreign_key for models > #{@association.model.model_name} > associations > has_one > #{@has_one_name}\n" unless @has_one_manifest['foreign_key']
           @foreign_key = @has_one_manifest['foreign_key']
         end
         
index f093ae7..46d7412 100644 (file)
@@ -12,6 +12,7 @@ module Manifest
       end
       
       def set_default
+        raise "undefined type for models > #{self.model_name} > attributes > #{@attribute_name}\n" unless @attribute_manifest['type']
         @attribute_manifest['primary_key'] ||= 0
         @attribute_manifest['rules'] ||= {}
       end
index 1b93aa0..e7c1803 100644 (file)
@@ -1,10 +1,33 @@
-require "manifest/model/list/base"
-require "manifest/model/list/public"
-require "manifest/model/list/private"
-require "manifest/model/list/system_resource"
-require "manifest/model/list/has_many"
-require "manifest/model/list/has_many_through"
-require "manifest/model/list/filter"
-require "manifest/model/list/through_filter"
-require "manifest/model/list/element_filter"
-require "manifest/model/list/play"
+require_dependency "manifest/model/list/base"
+require_dependency "manifest/model/list/public"
+require_dependency "manifest/model/list/private"
+require_dependency "manifest/model/list/system_resource"
+require_dependency "manifest/model/list/has_many"
+require_dependency "manifest/model/list/has_many_through"
+require_dependency "manifest/model/list/filter"
+require_dependency "manifest/model/list/through_filter"
+require_dependency "manifest/model/list/element_filter"
+require_dependency "manifest/model/list/play"
+module Manifest
+  module ModelModule
+    class ListFactory
+      include ListModule
+      @@types = {
+        'public' => PublicList, 'private' => PrivateList, 'system_resource' => SystemResourceList,
+        'has_many' => HasManyList, 'has_many_through' => HasManyThroughList, 'filter' => FilterList, 
+        'through_filter' => ThroughFilterList, 'element_filter' => ElementFilterList, 
+        'play' => PlayList
+      }
+      
+      def self.factory model, my_name, my_manifest
+        type = my_manifest['type']
+        raise "undefined type for models > #{model.model_name} > lists > #{my_name}\n" unless type
+        my_class = @@types[type]
+        raise "undefined class for models > #{model.model_name} > lists > #{my_name} > #{type}\n" unless my_class
+        my_class.new(model, my_name, my_manifest)
+      end
+      
+    end
+    
+  end
+end
index 5876616..7ab98ba 100644 (file)
@@ -1,6 +1,6 @@
-require "manifest/profiler/column"
-require "manifest/profiler/list"
-require "manifest/profiler/association"
+require_dependency "manifest/profiler/column"
+require_dependency "manifest/profiler/list"
+require_dependency "manifest/profiler/association"
 module Manifest
   class Profiler
     
index 036d477..c07fc20 100644 (file)
@@ -1,6 +1,6 @@
-require "manifest/profiler/association/belongs_to"
-require "manifest/profiler/association/has_many"
-require "manifest/profiler/association/has_one"
+require_dependency "manifest/profiler/association/belongs_to"
+require_dependency "manifest/profiler/association/has_many"
+require_dependency "manifest/profiler/association/has_one"
 module Manifest
   module ProfilerModule
     class Association
similarity index 100%
rename from lib/filer/date.rb
rename to lib/view/filer/date.rb
similarity index 100%
rename from lib/filer/edit.rb
rename to lib/view/filer/edit.rb
similarity index 100%
rename from lib/filer/filer.rb
rename to lib/view/filer/filer.rb
similarity index 100%
rename from lib/filer/icon.rb
rename to lib/view/filer/icon.rb
similarity index 100%
rename from lib/filer/symbol.rb
rename to lib/view/filer/symbol.rb
diff --git a/lib/view/form/form.rb b/lib/view/form/form.rb
new file mode 100644 (file)
index 0000000..67746fd
--- /dev/null
@@ -0,0 +1,260 @@
+require_dependency "manifest/form/field"
+module Manifest
+  class Form
+    
+    include ProfilerModule
+    def self.manager manifest, my_manifests
+      my_manifests.map {|item_name, form_manifest|
+        self.new(manifest, item_name, form_manifest)
+      }
+    end
+    
+    attr :form_manifest, :item_name, :manifest, 
+      :base, :fields, :field_names
+    def initialize manifest, item_name, form_manifest
+      @manifest = manifest
+      @item_name = item_name
+      @form_manifest = form_manifest
+      self.set_default
+      self.init
+    end
+    
+    def set_default
+      @form_manifest['fields'] ||= {}
+      @form_manifest['field_names'] ||= []
+    end
+    
+    def init
+      @base = @form_manifest['base']
+      @fields = {}
+      @form_manifest['fields'].each {|field_name, field_manifest|
+        @fields[field_name] = List.new(self, field_name, field_manifest)
+      }
+      @field_names = @form_manifest['field_names']
+    end
+    
+  end
+  
+
+module Pettanr
+  class FormManager
+    class Form
+      class Field
+        class Text
+          def initialize conf, field
+            @conf = conf
+            @field = field
+          end
+          
+          def tag_options
+            opt = @field.tag_options.merge(@conf['options'] || {})
+            @field.element.field_tag_attributes(@field.column, @field.tag_mounted, opt)
+          end
+          
+          def render view
+            view.text_field_tag @field.tag_name, @field.tag_value, self.tag_options
+          end
+          
+        end
+        
+        class TextArea < Text
+          def render view
+            view.text_area_tag @field.tag_name, @field.tag_value, self.tag_options
+          end
+          
+        end
+        
+        class Number < Text
+          def render view
+            view.number_field_tag @field.tag_name, @field.tag_value, self.tag_options
+          end
+          
+        end
+        
+        class Hidden < Text
+          def render view
+            view.hidden_field_tag @field.tag_name, @field.tag_value, self.tag_options
+          end
+          
+        end
+        
+        class Select < Text
+          def initialize conf, field
+            super
+            @model = Pettanr::Application::manifest.model(@field.model_name)
+            @source_conf = @model.attributes[@field.column]['source']
+          end
+          
+          def items
+            Pettanr::Application::manifest.select_items[@source_conf['type']][@source_conf['key']]
+          end
+          
+          def render view
+            view.select_tag @field.tag_name, 
+              view.options_for_select(view.t_select_items(self.items), :selected => @field.tag_value.to_s ), self.tag_options
+          end
+          
+        end
+        
+        class Helper
+          attr :field
+          def initialize field, name, conf
+            @conf = conf
+            @field = field
+            @name = name
+          end
+          
+          def wrapper
+            @conf['wrapper']
+          end
+          
+          def path
+            @conf['path']
+          end
+          
+          def options
+            @conf['options']
+          end
+          
+        end
+        
+        attr :part, :column, :type, :mounted, :model_name, :tag_options, :helpers, :form
+        @@type = {
+          'text' => Text, 'text_area' => TextArea, 'number' => Number, 
+          'hidden' => Hidden, 'select' => Select
+        }
+        def initialize form, mounted, conf, manifest
+          @form = form
+          @mounted = mounted
+          @conf = conf
+          @manifest = manifest
+          
+          @model_name = @conf['model'] || @form.model_name
+          @part = @conf['part']
+          @column = @conf['column']
+          @label_conf = @conf['label'] || {}
+          @field_conf = @conf['field']
+          @helper_confs = @conf['helpers'] || {}
+          
+          @tag_options = {'data-model' => @model_name}
+          
+          @model_manifest =  Pettanr::Application::manifest.model(@model_name)
+          model_attribute_conf =  @model_manifest.attributes[self.column] || {}
+          @primary_key = model_attribute_conf['primary_key']
+          
+          @helpers = @helper_confs.map do |helper_name, helper_conf|
+            Helper.new self, helper_name, helper_conf
+          end
+        end
+        
+        def element
+          @element ||= if self.part?
+            @form.element.__send__ self.part
+          else
+            @form.element
+          end
+        end
+        
+        def part?
+          self.part != nil
+        end
+        
+        def ignore_field?
+          @primary_key and self.element.new_record?
+        end
+        
+        def label?
+          @label_conf['type'] == nil or @label_conf['type'] != 'hidden'
+        end
+        
+        def label view
+          view.t 'activerecord.attributes.' + self.model_name + '.' +  self.column
+        end
+        
+        def label_break?
+          @label_conf['row_break'] == true
+        end
+        
+        def tag_name
+          if self.part?
+            @form.model_name + '[' + self.model_name + '_attributes][' + self.column + ']'
+          else
+            @form.model_name + '[' + self.column + ']'
+          end
+        end
+        
+        def tag_value
+          self.element.attributes[self.column]
+        end
+        
+        def tag_mounted
+          self.mounted ? 0 : 1
+        end
+        
+        def field
+          @field ||= @@type[@field_conf['type']].new @field_conf, self
+        end
+        
+        def has_helper?
+          !@helpers.empty?
+        end
+        
+        def row_break?
+          @conf['row_break'] == true
+        end
+        
+      end
+      
+      attr :element, :mounted, :attributes, :fields, :model_name
+      def initialize element, operators, mounted, manifest
+        @element = element
+        @operators = operators
+        @mounted = mounted
+        @manifest = manifest
+        
+        @base = @manifest.base
+        @model_name = @base || element.model_name
+        
+        base_field_confs = if @base
+          base_form = Pettanr::Application::manifest.form(@base)
+          base_form.fields
+        else
+          {}
+        end
+        extend_field_confs = @manifest.fields
+        @field_confs = base_field_confs.merge(extend_field_confs)
+        @fields = @manifest.field_names.map do |field_name|
+          field_conf = @field_confs[field_name]
+          Field.new self, @mounted, field_conf, manifest
+        end
+      end
+      
+      def name
+        @element.form_name
+      end
+      
+      def each_field
+        @fields.each do |field|
+          next if field.ignore_field?
+          yield field
+        end
+      end
+      
+    end
+    
+    attr :form_manifest, :item_name, :manifest, :form_conf
+    def initialize form_manifest
+      @form_manifest = form_manifest
+      @item_name = @form_manifest.item_name
+      @manifest = @form_manifest.manifest
+      @form_conf = @form_manifest.conf
+      
+    end
+    
+    def open element, operators, mounted
+      Form.new element, operators, mounted, @form_manifest
+    end
+    
+  end
+end
+
index 9d2d066..fc2a2d5 100644 (file)
         "has_many": {\r
           "scroll_panels": {\r
             "foreign_key": "scroll_id",\r
-            "model": "scroll_panel"\r
+            "model_name": "scroll_panel"\r
           },\r
           "panels": {\r
             "through": "scroll_panel",\r
             "foreign_key": "scroll_id",\r
-            "model": "panel"\r
+            "model_name": "panel"\r
           }\r
         }\r
       },\r
         "play": {\r
           "type": "play",\r
           "args": {\r
-            "model": "scroll_panel",\r
+            "model_name": "scroll_panel",\r
             "filter_key": "scroll_id"\r
           }\r
         }\r
         "has_many": {\r
           "stories": {\r
             "foreign_key": "comic_id",\r
-            "model": "story"\r
+            "model_name": "story"\r
           }\r
         },\r
         "has_many_through": {}\r
         "has_many": {\r
           "story_sheets": {\r
             "foreign_key": "story_id",\r
-            "model": "story_sheet"\r
+            "model_name": "story_sheet"\r
           },\r
           "sheets": {\r
             "through": "story_sheets",\r
             "foreign_key": "story_id",\r
-            "model": "sheet"\r
+            "model_name": "sheet"\r
           }\r
         }\r
       },\r
         "play": {\r
           "type": "play",\r
           "args": {\r
-            "model": "story_sheet",\r
+            "model_name": "story_sheet",\r
             "filter_key": "story_id"\r
           }\r
         }\r
         "has_many": {\r
           "story_sheets": {\r
             "foreign_key": "story_id",\r
-            "model": "story_sheet"\r
+            "model_name": "story_sheet"\r
           },\r
           "stories": {\r
             "through": "story_sheets",\r
             "foreign_key": "sheet_id",\r
-            "model": "story"\r
+            "model_name": "story"\r
           },\r
           "sheet_panels": {\r
             "foreign_key": "sheet_id",\r
-            "model": "sheet_panel"\r
+            "model_name": "sheet_panel"\r
           },\r
           "panels": {\r
             "through": "sheet_panels",\r
             "foreign_key": "sheet_id",\r
-            "model": "panel"\r
+            "model_name": "panel"\r
           }\r
         }\r
       },\r
         "play": {\r
           "type": "play",\r
           "args": {\r
-            "model": "sheet_panel",\r
+            "model_name": "sheet_panel",\r
             "filter_key": "sheet_id"\r
           }\r
         }\r
         "has_many": {\r
           "scroll_panels": {\r
             "foreign_key": "panel_id",\r
-            "model": "scroll_panel"\r
+            "model_name": "scroll_panel"\r
           },\r
           "scrolls": {\r
             "through": "scroll_panels",\r
             "foreign_key": "panel_id",\r
-            "model": "scroll"\r
+            "model_name": "scroll"\r
           },\r
           "sheet_panels": {\r
             "foreign_key": "panel_id",\r
-            "model": "sheet_panel"\r
+            "model_name": "sheet_panel"\r
           },\r
           "sheets": {\r
             "through": "sheet_panels",\r
             "foreign_key": "panel_id",\r
-            "model": "sheet"\r
+            "model_name": "sheet"\r
           },\r
           "panel_pictures": {\r
             "foreign_key": "panel_id",\r
-            "model": "panel_picture"\r
+            "model_name": "panel_picture"\r
           },\r
           "speech_balloons": {\r
             "foreign_key": "panel_id",\r
-            "model": "speech_balloon"\r
+            "model_name": "speech_balloon"\r
           },\r
           "ground_pictures": {\r
             "foreign_key": "panel_id",\r
-            "model": "ground_picture"\r
+            "model_name": "ground_picture"\r
           },\r
           "ground_colors": {\r
             "foreign_key": "panel_id",\r
-            "model": "ground_color"\r
+            "model_name": "ground_color"\r
           }\r
         }\r
       },\r
         "has_one": {\r
           "balloon": {\r
             "foreign_key": "speech_balloon_id",\r
-            "model": "balloon"\r
+            "model_name": "balloon"\r
           },\r
           "speech": {\r
             "foreign_key": "speech_balloon_id",\r
-            "model": "speech"\r
+            "model_name": "speech"\r
           }\r
         }\r
       },\r
         "has_many": {\r
           "pictures": {\r
             "foreign_key": "original_picture_id",\r
-            "model": "picture"\r
+            "model_name": "picture"\r
           }\r
         },\r
         "has_one": {\r
           "resource_picture": {\r
             "foreign_key": "original_picture_id",\r
-            "model": "resource_picture"\r
+            "model_name": "resource_picture"\r
           }\r
         }\r
       },\r
         "has_many": {\r
           "speech_balloons": {\r
             "foreign_key": "speech_balloon_template_id",\r
-            "model": "speech_balloon"\r
+            "model_name": "speech_balloon"\r
           },\r
           "panels": {\r
             "through": "speech_balloons",\r
             "foreign_key": "speech_balloon_template_id",\r
-            "model": "panel"\r
+            "model_name": "panel"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "speeches": {\r
             "foreign_key": "writing_format_id",\r
-            "model": "speech"\r
+            "model_name": "speech"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "licenses": {\r
             "foreign_key": "license_group_id",\r
-            "model": "license"\r
+            "model_name": "license"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "resource_pictures": {\r
             "foreign_key": "license_id",\r
-            "model": "resource_picture"\r
+            "model_name": "resource_picture"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "scrolls": {\r
             "foreign_key": "author_id",\r
-            "model": "scroll"\r
+            "model_name": "scroll"\r
           },\r
           "comics": {\r
             "foreign_key": "author_id",\r
-            "model": "comic"\r
+            "model_name": "comic"\r
           },\r
           "stories": {\r
             "foreign_key": "author_id",\r
-            "model": "story"\r
+            "model_name": "story"\r
           },\r
           "sheets": {\r
             "foreign_key": "author_id",\r
-            "model": "sheet"\r
+            "model_name": "sheet"\r
           },\r
           "panels": {\r
             "foreign_key": "author_id",\r
-            "model": "panel"\r
+            "model_name": "panel"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "resource_pictures": {\r
             "foreign_key": "artist_id",\r
-            "model": "resource_picture"\r
+            "model_name": "resource_picture"\r
           }\r
         },\r
         "has_one": {}\r
         "has_many": {\r
           "balloons": {\r
             "foreign_key": "system_picture_id",\r
-            "model": "balloon"\r
+            "model_name": "balloon"\r
           },\r
           "balloon_templates": {\r
             "foreign_key": "system_picture_id",\r
-            "model": "balloon_template"\r
+            "model_name": "balloon_template"\r
           },\r
           "licenses": {\r
             "foreign_key": "system_picture_id",\r
-            "model": "license"\r
+            "model_name": "license"\r
           }\r
         },\r
         "has_one": {}\r
       }\r
     ],\r
     "forms": {\r
-      "Panel": "panel",\r
-      "panel": {\r
-        "fields": {\r
-          "caption": {\r
-            "column": "caption",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
-            },\r
-            "row_break": true\r
-          },\r
-          "width": {\r
-            "column": "width",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+      "base": {\r
+        "panel": {\r
+          "fields": {\r
+            "caption": {\r
+              "args": {\r
+                "column": "caption",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
               }\r
-            }\r
-          },\r
-          "height": {\r
-            "column": "height",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            },\r
+            "width": {\r
+              "args": {\r
+                "column": "width",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "border": {\r
-            "column": "border",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "height": {\r
+              "args": {\r
+                "column": "height",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
-            }\r
-          },\r
-          "publish": {\r
-            "column": "publish",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select"\r
             },\r
-            "row_break": true\r
-          },\r
-          "id": {\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "border": {\r
+              "args": {\r
+                "column": "border",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "author_id": {\r
-            "column": "author_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "publish": {\r
+              "args": {\r
+                "column": "publish",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
-        },\r
-        "field_names": [\r
-          "caption",\r
-          "width",\r
-          "height",\r
-          "border",\r
-          "publish",\r
-          "id",\r
-          "author_id"\r
-        ]\r
-      },\r
-      "PanelPicture": "panel_picture",\r
-      "panel_picture": {\r
-        "fields": {\r
-          "caption": {\r
-            "column": "caption",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
+            "id": {\r
+              "args": {\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none "\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "x": {\r
-            "column": "x",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "author_id": {\r
+              "args": {\r
+                "column": "author_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
             }\r
           },\r
-          "y": {\r
-            "column": "y",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+          "field_names": [\r
+            "caption",\r
+            "width",\r
+            "height",\r
+            "border",\r
+            "publish",\r
+            "id",\r
+            "author_id"\r
+          ]\r
+        },\r
+        "panel_picture": {\r
+          "fields": {\r
+            "caption": {\r
+              "args": {\r
+                "column": "caption",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "width": {\r
-            "column": "width",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "x": {\r
+              "args": {\r
+                "column": "x",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
             },\r
-            "helpers": {\r
-              "size": {\r
-                "path": "panels/size_helper",\r
-                "options": {\r
-                  "class": "panel_picture_width_tool"\r
-                }\r
+            "y": {\r
+              "args": {\r
+                "column": "y",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "height": {\r
-            "column": "height",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "width": {\r
+              "args": {\r
+                "column": "width",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "helpers": {\r
+                  "size": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/size_helper",\r
+                      "class": "panel_picture_width_tool"\r
+                    }\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "helpers": {\r
-              "size": {\r
-                "path": "panels/size_helper",\r
-                "options": {\r
-                  "class": "panel_picture_height_tool"\r
-                }\r
+            "height": {\r
+              "args": {\r
+                "column": "height",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "helpers": {\r
+                  "size": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/size_helper",\r
+                      "class": "panel_picture_height_tool"\r
+                    }\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "link": {\r
-            "column": "link",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
+            "link": {\r
+              "args": {\r
+                "column": "link",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "id": {\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "id": {\r
+              "args": {\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "panel_id": {\r
-            "column": "panel_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "panel_id": {\r
+              "args": {\r
+                "column": "panel_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "picture_id": {\r
-            "column": "picture_id",\r
-            "label": {},\r
-            "field": {\r
-              "type": "hidden"\r
+            "picture_id": {\r
+              "args": {\r
+                "column": "picture_id",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "hidden"\r
+                },\r
+                "helpers": {\r
+                  "popup": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/popup_helper",\r
+                      "source": "pictures"\r
+                    }\r
+                  }\r
+                }\r
+              }\r
             },\r
-            "helpers": {\r
-              "popup": {\r
-                "path": "panels/popup_helper",\r
-                "source": "pictures",\r
-                "options": {}\r
+            "z": {\r
+              "args": {\r
+                "column": "z",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
-            }\r
-          },\r
-          "z": {\r
-            "column": "z",\r
-            "label": {\r
-              "type": "hidden"\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
+            "t": {\r
+              "args": {\r
+                "column": "t",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             }\r
           },\r
-          "t": {\r
-            "column": "t",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
+          "field_names": [\r
+            "caption",\r
+            "x",\r
+            "y",\r
+            "width",\r
+            "height",\r
+            "link",\r
+            "id",\r
+            "panel_id",\r
+            "picture_id",\r
+            "z",\r
+            "t"\r
+          ]\r
         },\r
-        "field_names": [\r
-          "caption",\r
-          "x",\r
-          "y",\r
-          "width",\r
-          "height",\r
-          "link",\r
-          "id",\r
-          "panel_id",\r
-          "picture_id",\r
-          "z",\r
-          "t"\r
-        ]\r
-      },\r
-      "speech_balloon": {\r
-        "fields": {\r
-          "speech_balloon.id": {\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.panel_id": {\r
-            "column": "panel_id",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.speech_balloon_template_id": {\r
-            "column": "speech_balloon_template_id",\r
-            "label": {\r
-              "type": "hidden"\r
+        "speech_balloon": {\r
+          "fields": {\r
+            "speech_balloon.id": {\r
+              "args": {\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.caption": {\r
-            "column": "caption",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
+            "speech_balloon.panel_id": {\r
+              "args": {\r
+                "column": "panel_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "speech_balloon.z": {\r
-            "column": "z",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.speech_balloon_template_id": {\r
+              "args": {\r
+                "column": "speech_balloon_template_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.t": {\r
-            "column": "t",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.caption": {\r
+              "args": {\r
+                "column": "caption",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.classname": {\r
-            "column": "classname",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.z": {\r
+              "args": {\r
+                "column": "z",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech_balloon.settings": {\r
-            "column": "settings",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.t": {\r
+              "args": {\r
+                "column": "t",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "balloon.id": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.classname": {\r
+              "args": {\r
+                "column": "classname",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "balloon.speech_balloon_id": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "speech_balloon_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech_balloon.settings": {\r
+              "args": {\r
+                "column": "settings",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "balloon.system_picture_id": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "system_picture_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "balloon.id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "balloon.r": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "r",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "balloon.speech_balloon_id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "speech_balloon_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
             },\r
-            "helpers": {\r
-              "tail_angle": {\r
-                "path": "panels/tail_angle_helper",\r
-                "options": {}\r
+            "balloon.system_picture_id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "system_picture_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "balloon.x": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "x",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "balloon.r": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "r",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "helpers": {\r
+                  "tail_angle": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/tail_angle_helper"\r
+                    }\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
-            }\r
-          },\r
-          "balloon.y": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "y",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            },\r
+            "balloon.x": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "x",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "balloon.width": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "width",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "balloon.y": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "y",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
-            }\r
-          },\r
-          "balloon.height": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "height",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            },\r
+            "balloon.width": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "width",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "balloon.settings": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "settings",\r
-            "label": {\r
-              "type": "hidden"\r
+            "balloon.height": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "height",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.id": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "balloon.settings": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "settings",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.speech_balloon_id": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "speech_balloon_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.x": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "x",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.speech_balloon_id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "speech_balloon_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.y": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "y",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.x": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "x",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.width": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "width",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.y": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "y",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.height": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "height",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.width": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "width",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "speech.writing_format_id": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "writing_format_id",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select"\r
-            }\r
-          },\r
-          "speech.font_size": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "font_size",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select"\r
+            "speech.height": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "height",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "speech.text_align": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "text_align",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select"\r
-            }\r
-          },\r
-          "speech.quotes": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "quotes",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text",\r
-              "options": {\r
-                "size": 5\r
+            "speech.writing_format_id": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "writing_format_id",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select"\r
+                }\r
               }\r
-            }\r
-          },\r
-          "speech.content": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "content",\r
-            "label": {\r
-              "row_break": true\r
             },\r
-            "field": {\r
-              "type": "text_area",\r
-              "options": {\r
-                "size": "45x5"\r
+            "speech.font_size": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "font_size",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select"\r
+                },\r
+                "row_break": true\r
               }\r
-            }\r
-          },\r
-          "speech.fore_color": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "fore_color",\r
-            "label": {\r
-              "row_break": true\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
+            "speech.text_align": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "text_align",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select"\r
+                }\r
+              }\r
             },\r
-            "helpers": {\r
-              "color": {\r
-                "path": "panels/color_helper",\r
-                "options": {},\r
-                "wrapper": "speech-fore_color-wrap"\r
+            "speech.quotes": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "quotes",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
-            }\r
-          },\r
-          "speech.settings": {\r
-            "model": "speech",\r
-            "part": "speech",\r
-            "column": "settings",\r
-            "label": {\r
-              "type": "hidden"\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
-        }\r
-      },\r
-      "CircleSpeechBalloon": {\r
-        "base": "speech_balloon",\r
-        "fields": {},\r
-        "field_names": [\r
-          "speech_balloon.caption",\r
-          "balloon.r",\r
-          "balloon.x",\r
-          "balloon.y",\r
-          "balloon.width",\r
-          "balloon.height",\r
-          "balloon.id",\r
-          "balloon.speech_balloon_id",\r
-          "balloon.system_picture_id",\r
-          "balloon.settings",\r
-          "speech.writing_format_id",\r
-          "speech.font_size",\r
-          "speech.text_align",\r
-          "speech.quotes",\r
-          "speech.content",\r
-          "speech.fore_color",\r
-          "speech.id",\r
-          "speech.speech_balloon_id",\r
-          "speech.x",\r
-          "speech.y",\r
-          "speech.width",\r
-          "speech.height",\r
-          "speech.settings",\r
-          "speech_balloon.id",\r
-          "speech_balloon.panel_id",\r
-          "speech_balloon.speech_balloon_template_id",\r
-          "speech_balloon.classname",\r
-          "speech_balloon.z",\r
-          "speech_balloon.t",\r
-          "speech_balloon.settings"\r
-        ]\r
-      },\r
-      "PlainSpeechBalloon": {\r
-        "base": "speech_balloon",\r
-        "fields": {\r
-          "balloon.r": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "r",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.content": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "content",\r
+                "label": {\r
+                  "row_break": true\r
+                },\r
+                "tag": {\r
+                  "type": "text_area",\r
+                  "args": {\r
+                    "size": "45x5"\r
+                  }\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
-        },\r
-        "field_names": [\r
-          "speech_balloon.caption",\r
-          "balloon.r",\r
-          "balloon.x",\r
-          "balloon.y",\r
-          "balloon.width",\r
-          "balloon.height",\r
-          "balloon.id",\r
-          "balloon.speech_balloon_id",\r
-          "balloon.system_picture_id",\r
-          "balloon.settings",\r
-          "speech.writing_format_id",\r
-          "speech.font_size",\r
-          "speech.text_align",\r
-          "speech.quotes",\r
-          "speech.content",\r
-          "speech.fore_color",\r
-          "speech.id",\r
-          "speech.speech_balloon_id",\r
-          "speech.x",\r
-          "speech.y",\r
-          "speech.width",\r
-          "speech.height",\r
-          "speech.settings",\r
-          "speech_balloon.id",\r
-          "speech_balloon.panel_id",\r
-          "speech_balloon.speech_balloon_template_id",\r
-          "speech_balloon.classname",\r
-          "speech_balloon.z",\r
-          "speech_balloon.t",\r
-          "speech_balloon.settings"\r
-        ]\r
-      },\r
-      "SquareSpeechBalloon": {\r
-        "base": "speech_balloon",\r
-        "fields": {\r
-          "balloon.r": {\r
-            "model": "balloon",\r
-            "part": "balloon",\r
-            "column": "r",\r
-            "label": {\r
-              "type": "hidden"\r
+            "speech.fore_color": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "fore_color",\r
+                "label": {\r
+                  "row_break": true\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                },\r
+                "helpers": {\r
+                  "color": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/color_helper",\r
+                      "wrapper": "speech-fore_color-wrap"\r
+                    }\r
+                  }\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
+            "speech.settings": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "speech",\r
+                "part": "speech",\r
+                "column": "settings",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             }\r
           }\r
         },\r
-        "field_names": [\r
-          "speech_balloon.caption",\r
-          "balloon.r",\r
-          "balloon.x",\r
-          "balloon.y",\r
-          "balloon.width",\r
-          "balloon.height",\r
-          "balloon.id",\r
-          "balloon.speech_balloon_id",\r
-          "balloon.system_picture_id",\r
-          "balloon.settings",\r
-          "speech.writing_format_id",\r
-          "speech.font_size",\r
-          "speech.text_align",\r
-          "speech.quotes",\r
-          "speech.content",\r
-          "speech.fore_color",\r
-          "speech.id",\r
-          "speech.speech_balloon_id",\r
-          "speech.x",\r
-          "speech.y",\r
-          "speech.width",\r
-          "speech.height",\r
-          "speech.settings",\r
-          "speech_balloon.id",\r
-          "speech_balloon.panel_id",\r
-          "speech_balloon.speech_balloon_template_id",\r
-          "speech_balloon.classname",\r
-          "speech_balloon.z",\r
-          "speech_balloon.t",\r
-          "speech_balloon.settings"\r
-        ]\r
-      },\r
-      "GroundPicture": "ground_picture",\r
-      "ground_picture": {\r
-        "fields": {\r
-          "id": {\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+        "ground_picture": {\r
+          "fields": {\r
+            "id": {\r
+              "args": {\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "panel_id": {\r
-            "column": "panel_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "panel_id": {\r
+              "args": {\r
+                "column": "panel_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "picture_id": {\r
-            "column": "picture_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "picture_id": {\r
+              "args": {\r
+                "column": "picture_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "caption": {\r
-            "column": "caption",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
+            "caption": {\r
+              "args": {\r
+                "column": "caption",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "repeat": {\r
-            "column": "repeat",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select",\r
-              "options": {\r
-                "source": "magic_number",\r
-                "key": "ground_picture_repeat_items"\r
+            "repeat": {\r
+              "args": {\r
+                "column": "repeat",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select",\r
+                  "args": {\r
+                    "source": "magic_number",\r
+                    "key": "ground_picture_repeat_items"\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "x": {\r
-            "column": "x",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "x": {\r
+              "args": {\r
+                "column": "x",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
               }\r
-            }\r
-          },\r
-          "y": {\r
-            "column": "y",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            },\r
+            "y": {\r
+              "args": {\r
+                "column": "y",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "z": {\r
-            "column": "z",\r
-            "label": {\r
-              "type": "hidden"\r
+            "z": {\r
+              "args": {\r
+                "column": "z",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
+            "t": {\r
+              "args": {\r
+                "column": "t",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             }\r
           },\r
-          "t": {\r
-            "column": "t",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
+          "field_names": [\r
+            "caption",\r
+            "repeat",\r
+            "x",\r
+            "y",\r
+            "z",\r
+            "t",\r
+            "id",\r
+            "panel_id",\r
+            "picture_id"\r
+          ]\r
         },\r
-        "field_names": [\r
-          "caption",\r
-          "repeat",\r
-          "x",\r
-          "y",\r
-          "z",\r
-          "t",\r
-          "id",\r
-          "panel_id",\r
-          "picture_id"\r
-        ]\r
-      },\r
-      "GroundColor": "ground_color",\r
-      "ground_color": {\r
-        "fields": {\r
-          "id": {\r
-            "column": "id",\r
-            "label": {\r
-              "type": "hidden"\r
+        "ground_color": {\r
+          "fields": {\r
+            "id": {\r
+              "args": {\r
+                "column": "id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "panel_id": {\r
-            "column": "panel_id",\r
-            "label": {\r
-              "type": "hidden"\r
+            "panel_id": {\r
+              "args": {\r
+                "column": "panel_id",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          },\r
-          "caption": {\r
-            "column": "caption",\r
-            "label": {},\r
-            "field": {\r
-              "type": "text"\r
+            "caption": {\r
+              "args": {\r
+                "column": "caption",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "text"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "code": {\r
-            "column": "code",\r
-            "label": {\r
-              "row_break": true\r
+            "code": {\r
+              "args": {\r
+                "column": "code",\r
+                "label": {\r
+                  "row_break": true\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                },\r
+                "helpers": {\r
+                  "color": {\r
+                    "type": "size",\r
+                    "args": {\r
+                      "path": "panels/color_helper",\r
+                      "wrapper": "ground_color-code-wrap"\r
+                    }\r
+                  }\r
+                },\r
+                "row_break": true\r
+              }\r
+            },\r
+            "orientation": {\r
+              "args": {\r
+                "column": "orientation",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "select"\r
+                },\r
+                "row_break": true\r
+              }\r
             },\r
-            "field": {\r
-              "type": "hidden"\r
+            "xy": {\r
+              "args": {\r
+                "column": "xy",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                }\r
+              }\r
             },\r
-            "helpers": {\r
-              "color": {\r
-                "path": "panels/color_helper",\r
-                "options": {},\r
-                "wrapper": "ground_color-code-wrap"\r
+            "wh": {\r
+              "args": {\r
+                "column": "wh",\r
+                "label": {},\r
+                "tag": {\r
+                  "type": "number",\r
+                  "args": {\r
+                    "size": 5\r
+                  }\r
+                },\r
+                "row_break": true\r
               }\r
             },\r
-            "row_break": true\r
-          },\r
-          "orientation": {\r
-            "column": "orientation",\r
-            "label": {},\r
-            "field": {\r
-              "type": "select"\r
+            "z": {\r
+              "args": {\r
+                "column": "z",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
             },\r
-            "row_break": true\r
-          },\r
-          "xy": {\r
-            "column": "xy",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+            "t": {\r
+              "args": {\r
+                "column": "t",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
             }\r
           },\r
-          "wh": {\r
-            "column": "wh",\r
-            "label": {},\r
-            "field": {\r
-              "type": "number",\r
-              "options": {\r
-                "size": 5\r
+          "field_names": [\r
+            "id",\r
+            "panel_id",\r
+            "caption",\r
+            "code",\r
+            "orientation",\r
+            "xy",\r
+            "wh",\r
+            "z",\r
+            "t"\r
+          ]\r
+        }\r
+      },\r
+      "extend": {\r
+        "CircleSpeechBalloon": {\r
+          "base": "speech_balloon",\r
+          "fields": {},\r
+          "field_names": [\r
+            "speech_balloon.caption",\r
+            "balloon.r",\r
+            "balloon.x",\r
+            "balloon.y",\r
+            "balloon.width",\r
+            "balloon.height",\r
+            "balloon.id",\r
+            "balloon.speech_balloon_id",\r
+            "balloon.system_picture_id",\r
+            "balloon.settings",\r
+            "speech.writing_format_id",\r
+            "speech.font_size",\r
+            "speech.text_align",\r
+            "speech.quotes",\r
+            "speech.content",\r
+            "speech.fore_color",\r
+            "speech.id",\r
+            "speech.speech_balloon_id",\r
+            "speech.x",\r
+            "speech.y",\r
+            "speech.width",\r
+            "speech.height",\r
+            "speech.settings",\r
+            "speech_balloon.id",\r
+            "speech_balloon.panel_id",\r
+            "speech_balloon.speech_balloon_template_id",\r
+            "speech_balloon.classname",\r
+            "speech_balloon.z",\r
+            "speech_balloon.t",\r
+            "speech_balloon.settings"\r
+          ]\r
+        },\r
+        "PlainSpeechBalloon": {\r
+          "base": "speech_balloon",\r
+          "fields": {\r
+            "balloon.r": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "r",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
               }\r
-            },\r
-            "row_break": true\r
-          },\r
-          "z": {\r
-            "column": "z",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
             }\r
           },\r
-          "t": {\r
-            "column": "t",\r
-            "label": {\r
-              "type": "hidden"\r
-            },\r
-            "field": {\r
-              "type": "hidden"\r
-            }\r
-          }\r
+          "field_names": [\r
+            "speech_balloon.caption",\r
+            "balloon.r",\r
+            "balloon.x",\r
+            "balloon.y",\r
+            "balloon.width",\r
+            "balloon.height",\r
+            "balloon.id",\r
+            "balloon.speech_balloon_id",\r
+            "balloon.system_picture_id",\r
+            "balloon.settings",\r
+            "speech.writing_format_id",\r
+            "speech.font_size",\r
+            "speech.text_align",\r
+            "speech.quotes",\r
+            "speech.content",\r
+            "speech.fore_color",\r
+            "speech.id",\r
+            "speech.speech_balloon_id",\r
+            "speech.x",\r
+            "speech.y",\r
+            "speech.width",\r
+            "speech.height",\r
+            "speech.settings",\r
+            "speech_balloon.id",\r
+            "speech_balloon.panel_id",\r
+            "speech_balloon.speech_balloon_template_id",\r
+            "speech_balloon.classname",\r
+            "speech_balloon.z",\r
+            "speech_balloon.t",\r
+            "speech_balloon.settings"\r
+          ]\r
         },\r
-        "field_names": [\r
-          "id",\r
-          "panel_id",\r
-          "caption",\r
-          "code",\r
-          "orientation",\r
-          "xy",\r
-          "wh",\r
-          "z",\r
-          "t"\r
-        ]\r
+        "SquareSpeechBalloon": {\r
+          "base": "speech_balloon",\r
+          "fields": {\r
+            "balloon.r": {\r
+              "type": "part",\r
+              "args": {\r
+                "model": "balloon",\r
+                "part": "balloon",\r
+                "column": "r",\r
+                "label": {\r
+                  "type": "none"\r
+                },\r
+                "tag": {\r
+                  "type": "hidden"\r
+                }\r
+              }\r
+            }\r
+          },\r
+          "field_names": [\r
+            "speech_balloon.caption",\r
+            "balloon.r",\r
+            "balloon.x",\r
+            "balloon.y",\r
+            "balloon.width",\r
+            "balloon.height",\r
+            "balloon.id",\r
+            "balloon.speech_balloon_id",\r
+            "balloon.system_picture_id",\r
+            "balloon.settings",\r
+            "speech.writing_format_id",\r
+            "speech.font_size",\r
+            "speech.text_align",\r
+            "speech.quotes",\r
+            "speech.content",\r
+            "speech.fore_color",\r
+            "speech.id",\r
+            "speech.speech_balloon_id",\r
+            "speech.x",\r
+            "speech.y",\r
+            "speech.width",\r
+            "speech.height",\r
+            "speech.settings",\r
+            "speech_balloon.id",\r
+            "speech_balloon.panel_id",\r
+            "speech_balloon.speech_balloon_template_id",\r
+            "speech_balloon.classname",\r
+            "speech_balloon.z",\r
+            "speech_balloon.t",\r
+            "speech_balloon.settings"\r
+          ]\r
+        }\r
       }\r
     }\r
   }\r