OSDN Git Service

Merge branch 'v06sheet' of git.sourceforge.jp:/gitroot/pettanr/pettanr into v06sheet v06sheet
authoryasushiito <yas@pen-chan.jp>
Mon, 28 Oct 2013 01:43:03 +0000 (10:43 +0900)
committeryasushiito <yas@pen-chan.jp>
Mon, 28 Oct 2013 01:43:03 +0000 (10:43 +0900)
39 files changed:
Gemfile
app/assets/javascripts/application.js
app/assets/javascripts/configurations.js.coffee [new file with mode: 0644]
app/assets/javascripts/panels.js.coffee
app/assets/javascripts/pettanr_editor.js.coffee
app/assets/stylesheets/test.css.scss
app/controllers/application_controller.rb
app/controllers/ground_colors_controller.rb
app/controllers/ground_pictures_controller.rb
app/controllers/panel_pictures_controller.rb
app/controllers/speech_balloons_controller.rb
app/helpers/application_helper.rb
app/models/panel.rb
app/models/speech_balloon.rb
app/views/comics/_form.html.erb
app/views/ground_colors/_form.html.erb
app/views/ground_pictures/_form.html.erb
app/views/home/index.html.erb
app/views/layouts/test.html.erb
app/views/panel_pictures/_form.html.erb
app/views/panels/_element_form.html.erb [new file with mode: 0644]
app/views/panels/_element_tab.html.erb
app/views/panels/_form.html.erb
app/views/panels/_size_helper.html.erb
app/views/scroll_panels/_form.html.erb
app/views/scroll_panels/edit.html.erb
app/views/scrolls/_form.html.erb
app/views/scrolls/show.html.erb
app/views/sheet_panels/_form.html.erb
app/views/sheets/_form.html.erb
app/views/speech_balloons/_form.html.erb [deleted file]
app/views/stories/_form.html.erb
app/views/story_sheets/_form.html.erb
app/views/story_sheets/edit.html.erb
config/application.rb
db/migrate/20130911043458_copy_to_scroll.rb
lib/element.rb
public/not_work.html [new file with mode: 0644]
spec/models/panel_spec.rb

diff --git a/Gemfile b/Gemfile
index dcd755b..80208ee 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -33,6 +33,7 @@ end
 
 gem 'jquery-rails'
 gem 'jquery-ui-rails'
+gem "jquery-validation-rails"
 
 # To use ActiveModel has_secure_password
 gem 'bcrypt-ruby', '~> 3.0.0'
index ce8c00b..912b599 100644 (file)
@@ -7,7 +7,11 @@
 //= require jquery
 //= require jquery_ujs
 //= require jquery.ui.all
+//= require jquery.validate
+//= require jquery.validate.additional-methods
+//= require jquery.validate.localization/messages_ja
 //= require textchange
+//= require configurations
 //= require pettanr_editor
 //= require pettanr_sheeter
 //= require writing_formats
diff --git a/app/assets/javascripts/configurations.js.coffee b/app/assets/javascripts/configurations.js.coffee
new file mode 100644 (file)
index 0000000..091a42a
--- /dev/null
@@ -0,0 +1,1486 @@
+@configurations = {\r
+  models: {\r
+    Panel: 'panel',\r
+    panel: {\r
+      class_name: 'Panel',\r
+      table_name: 'panels',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        width: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        height: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        border: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        publish: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        author_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    PanelPicture: 'panel_picture',\r
+    panel_picture: {\r
+      class_name: 'PanelPicture',\r
+      table_name: 'panel_pictures',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        panel_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        picture_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        x: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        y: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        width: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        height: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        link: {\r
+          type: 'text',\r
+          rules : {\r
+            url: true,\r
+          }\r
+        },\r
+        z: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        t: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    SpeechBalloon: 'speech_balloon',\r
+    speech_balloon: {\r
+      class_name: 'SpeechBalloon',\r
+      table_name: 'speech_balloons',\r
+      extend: 'classname', \r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        panel_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        speech_balloon_template_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        classname: {\r
+          type: 'text',\r
+          rules : {\r
+            required: true,\r
+          }\r
+        },\r
+        z: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        t: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        settings: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    }, \r
+    Balloon: 'balloon',\r
+    balloon: {\r
+      class_name: 'Balloon',\r
+      table_name: 'balloons',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        speech_balloon_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        system_picture_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        x: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        y: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        width: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        height: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        r: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        settings: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    Speech: 'speech',\r
+    speech: {\r
+      class_name: 'Speech',\r
+      table_name: 'speeches',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        speech_balloon_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        writing_format_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        content: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        font_size: {\r
+          type: 'float',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        text_align: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            range: [0, 3],\r
+          }\r
+        },\r
+        fore_color: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            range: [0, 0xffffff],\r
+          }\r
+        },\r
+        x: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        y: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        width: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        height: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        quotes: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        settings: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    GroundPicture: 'ground_picture',\r
+    ground_picture: {\r
+      class_name: 'GroundPicture',\r
+      table_name: 'ground_pictures',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        panel_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        picture_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        repeat: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            range: [0, 3],\r
+          }\r
+        },\r
+        x: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        y: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        z: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        t: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    GroundColor: 'ground_color',\r
+    ground_color: {\r
+      class_name: 'GroundColor',\r
+      table_name: 'ground_colors',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        panel_id: {\r
+          type: 'number',\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+          }\r
+        },\r
+        code: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            range: [0, 0xffffff],\r
+          }\r
+        },\r
+        z: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 1,\r
+          }\r
+        },\r
+        t: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+            min: 0,\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+    WritingFormat: 'writing_format',\r
+    writing_format: {\r
+      class_name: 'WritingFormat',\r
+      table_name: 'writing_formats',\r
+      attributes: {\r
+        id: {\r
+          type: 'number',\r
+          primary_key: 1,\r
+          rules : {\r
+            number: true,\r
+          }\r
+        },\r
+        name: {\r
+          type: 'text',\r
+          rules : {\r
+            required: true,\r
+          }\r
+        },\r
+        classname: {\r
+          type: 'text',\r
+          rules : {\r
+            required: true,\r
+          }\r
+        },\r
+        caption: {\r
+          type: 'text',\r
+          rules : {\r
+            required: true,\r
+          }\r
+        },\r
+        system_picture_id: {\r
+          type: 'number',\r
+          rules : {\r
+            required: true,\r
+            number: true,\r
+          }\r
+        },\r
+        settings: {\r
+          type: 'text',\r
+          rules : {\r
+            required: true,\r
+          }\r
+        },\r
+        created_at: {\r
+          type: 'datetime',\r
+        },\r
+        updated_at: {\r
+          type: 'datetime',\r
+        }\r
+      }\r
+    },\r
+\r
+  },\r
+  elements: [\r
+    {\r
+      name: 'panel_picture',\r
+      path_name: 'panel_pictures', \r
+      parts: []\r
+    },\r
+    {\r
+      name: 'speech_balloon',\r
+      path_name: 'circle_speech_balloon/speech_balloons', \r
+      parts: ['balloon', 'speech']\r
+    },\r
+    {\r
+      name: 'ground_picture',\r
+      path_name: 'ground_pictures', \r
+      parts: []\r
+    },\r
+    {\r
+      name: 'ground_color',\r
+      path_name: 'ground_colors', \r
+      parts: []\r
+    },\r
+  ],\r
+  forms: {\r
+    Panel: 'panel',\r
+    panel: {\r
+      attributes: {\r
+        caption: {\r
+          column: 'caption',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        width: {\r
+          column: 'width',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          },\r
+        },\r
+        height: {\r
+          column: 'height',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }, \r
+        },\r
+        border: {\r
+          column: 'border',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          },\r
+        },\r
+        publish: {\r
+          column: 'publish',\r
+          type: 'select',\r
+          label: {\r
+          },\r
+          options: {\r
+            source: 'magic_number',\r
+            key: 'comic_visible_items',\r
+            size: 5, \r
+            row_break: true\r
+          }\r
+        },\r
+        id: {\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        author_id: {\r
+          column: 'author_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+      },\r
+      fields: [\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
+      attributes: {\r
+        caption: {\r
+          column: 'caption',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        x: {\r
+          column: 'x',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          }\r
+        },\r
+        y: {\r
+          column: 'y',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }\r
+        },\r
+        width: {\r
+          column: 'width',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          },\r
+          helpers: {\r
+            size: {\r
+              path: 'panels/size_helper',\r
+              options: {\r
+                class: 'panel_picture_width_tool', \r
+              }\r
+            }\r
+          },\r
+        },\r
+        height: {\r
+          column: 'height',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }, \r
+          helpers: {\r
+            size: {\r
+              path: 'panels/size_helper',\r
+              options: {\r
+                class: 'panel_picture_height_tool', \r
+              }\r
+            }\r
+          },\r
+        },\r
+        link: {\r
+          column: 'link',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        id: {\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        panel_id: {\r
+          column: 'panel_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        picture_id: {\r
+          column: 'picture_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        z: {\r
+          column: 'z',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        t: {\r
+          column: 't',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+      },\r
+      fields: [\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
+      attributes: {\r
+        'speech_balloon.id': {\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.panel_id': {\r
+          column: 'panel_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.speech_balloon_template_id': {\r
+          column: 'speech_balloon_template_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.caption': {\r
+          column: 'caption',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        'speech_balloon.z': {\r
+          column: 'z',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.t': {\r
+          column: 't',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.classname': {\r
+          column: 'classname',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech_balloon.settings': {\r
+          column: 'settings',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'balloon.id': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'balloon.speech_balloon_id': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'speech_balloon_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'balloon.system_picture_id': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'system_picture_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'balloon.r': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'r',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          },\r
+          helpers: {\r
+            tail_angle: {\r
+              path: 'panels/tail_angle_helper',\r
+              options: {\r
+              }\r
+            }\r
+          }\r
+        },\r
+        'balloon.x': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'x',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          }\r
+        },\r
+        'balloon.y': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'y',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }\r
+        },\r
+        'balloon.width': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'width',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          }\r
+        },\r
+        'balloon.height': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'height',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }\r
+        },\r
+        'balloon.settings': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'settings',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.id': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.speech_balloon_id': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'speech_balloon_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.x': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'x',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.y': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'y',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.width': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'width',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.height': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'height',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        'speech.writing_format_id': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'writing_format_id',\r
+          type: 'select',\r
+          label: {\r
+          },\r
+          options: {\r
+            source: 'model',\r
+            model: 'writing_format',\r
+            method: 'enable_list',\r
+            caption: 'caption'\r
+          }\r
+        },\r
+        'speech.font_size': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'font_size',\r
+          type: 'select',\r
+          label: {\r
+          },\r
+          options: {\r
+            source: 'magic_number',\r
+            key: 'speech_font_size_items',\r
+            row_break: true\r
+          }\r
+        },\r
+        'speech.text_align': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'text_align',\r
+          type: 'select',\r
+          label: {\r
+          },\r
+          options: {\r
+            source: 'magic_number',\r
+            key: 'speech_text_align_items',\r
+          }\r
+        },\r
+        'speech.quotes': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'quotes',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          }\r
+        },\r
+        'speech.content': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'content',\r
+          type: 'text_area',\r
+          label: {\r
+            row_break: true\r
+          },\r
+          options: {\r
+            size: '45x5', \r
+          }\r
+        },\r
+        'speech.fore_color': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'fore_color',\r
+          type: 'hidden',\r
+          label: {\r
+            row_break: true\r
+          },\r
+          options: {\r
+          },\r
+          helpers: {\r
+            color: {\r
+              path: 'panels/color_helper',\r
+              options: {\r
+              },\r
+              wrapper: 'speech-fore_color-wrap'\r
+            }\r
+          }\r
+        },\r
+        'speech.settings': {\r
+          model: 'speech',\r
+          part: 'speech',\r
+          column: 'settings',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+      },\r
+    },\r
+    CircleSpeechBalloon: 'circle_speech_balloon',\r
+    circle_speech_balloon: {\r
+      base: 'speech_balloon',\r
+      attributes: {\r
+      },\r
+      fields: [\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: 'plain_speech_balloon',\r
+    plain_speech_balloon: {\r
+      base: 'speech_balloon',\r
+      attributes: {\r
+        'balloon.r': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'r',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          },\r
+        },\r
+      },\r
+      fields: [\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: 'square_speech_balloon',\r
+    square_speech_balloon: {\r
+      base: 'speech_balloon',\r
+      attributes: {\r
+        'balloon.r': {\r
+          model: 'balloon',\r
+          part: 'balloon',\r
+          column: 'r',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          },\r
+        },\r
+      },\r
+      fields: [\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
+      attributes: {\r
+        id: {\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        panel_id: {\r
+          column: 'panel_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        picture_id: {\r
+          column: 'picture_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        caption: {\r
+          column: 'caption',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        repeat: {\r
+          column: 'repeat',\r
+          type: 'select',\r
+          label: {\r
+          },\r
+          options: {\r
+            source: 'magic_number',\r
+            key: 'ground_picture_repeat_items',\r
+            row_break: true\r
+          }\r
+        },\r
+        x: {\r
+          column: 'x',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+          }\r
+        },\r
+        y: {\r
+          column: 'y',\r
+          type: 'number',\r
+          label: {\r
+          },\r
+          options: {\r
+            size: 5, \r
+            row_break: true\r
+          }\r
+        },\r
+        z: {\r
+          column: 'z',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        t: {\r
+          column: 't',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+      },\r
+      fields: [\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
+      attributes: {\r
+        id: {\r
+          column: 'id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        panel_id: {\r
+          column: 'panel_id',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        caption: {\r
+          column: 'caption',\r
+          type: 'text',\r
+          label: {\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+        },\r
+        code: {\r
+          column: 'code',\r
+          type: 'hidden',\r
+          label: {\r
+            row_break: true\r
+          },\r
+          options: {\r
+            row_break: true\r
+          }\r
+          helpers: {\r
+            color: {\r
+              path: 'panels/color_helper',\r
+              options: {\r
+              },\r
+              wrapper: 'ground_color-code-wrap'\r
+            }\r
+          },\r
+        },\r
+        z: {\r
+          column: 'z',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+        t: {\r
+          column: 't',\r
+          type: 'hidden',\r
+          label: {\r
+            type: 'hidden'\r
+          },\r
+          options: {\r
+          }\r
+        },\r
+      },\r
+      fields: [\r
+        'id',\r
+        'panel_id',\r
+        'caption',\r
+        'code',\r
+        'z',\r
+        't',\r
+      ]\r
+    }\r
+  },\r
+  locales: {\r
+    ja: {\r
+    }\r
+  },\r
+}\r
+\r
+@repeat_texts = ['repeat', 'repeat-x', 'repeat-y', 'no-repeat']\r
+\r
+@text_align_texts = ['left', 'left', 'right', 'center']\r
+\r
index c203f09..c5466fe 100644 (file)
@@ -2,6 +2,7 @@ $ ->
   confirm_confirm_confirm = () ->\r
     confirm(  )\r
   editor = window.PettanrEditor\r
+  configurations =  window.configurations\r
   WritingFormat = window.PettanrWritingFormat\r
   WritingFormat.load($('#writing_formats'))\r
   SpeechBalloonTemplate = window.PettanrSpeechBalloonTemplate\r
@@ -12,6 +13,93 @@ $ ->
   PictureSizeHelper = window.PettanrPictureSizeHelper\r
   ColorHelper = window.PettanrColorHelper\r
   \r
+  find_configurations = ( hash, key) ->\r
+    if typeof(hash[key]) == 'string'\r
+      find_configurations(hash, hash[key])\r
+    else\r
+      return hash[key]\r
+  \r
+  set_validates = (form) ->\r
+    rules = {}\r
+    $('input', form).map ->\r
+      model_name = $(@).attr('data-model')\r
+      column_name = $(@).attr('column')\r
+      name = $(@).attr('name')\r
+      if model_name and column_name\r
+        model = find_configurations(configurations['models'], model_name)\r
+        rule = model['attributes'][column_name]['rules']\r
+        trace = editor.element_tag_id($(@)) \r
+        if rule\r
+          rules[name] = rule\r
+          $(@).focusout ->\r
+            if editor.is_panel(form)\r
+              validate_panel(form)\r
+            else\r
+              validate_element(form)\r
+    if Object.keys(rules).length > 0\r
+      v = form.validate({ignore:[],rules: rules})\r
+  \r
+  validate_panel = (form) ->\r
+    valid = form.valid()\r
+    bc = if valid\r
+      ''\r
+    else\r
+      '#ef29ef'\r
+    $('a', $('#tabs-1-tab')).map ->\r
+      $(@).css('background-color', bc)\r
+    valid\r
+  \r
+  display_element = (element, vis) ->\r
+    v = if vis\r
+      ''\r
+    else\r
+      'none'\r
+    trace = editor.element_tag_id(element)\r
+    switch element.attr('element_type')\r
+      when 'panel_picture'\r
+        trace = trace + 'div'\r
+    $(trace).css('display', v)\r
+  \r
+  validate_element = (form) ->\r
+    valid = form.valid()\r
+    bc = if valid\r
+      ''\r
+    else\r
+      '#ef29ef'\r
+    display_element(form, valid)\r
+    trace = editor.element_tag_id(form) \r
+    $('.elements-tab', $(trace + 'element_tab')).map  ->\r
+      $(@).css('background-color', bc)\r
+    valid\r
+  \r
+  validate_forms = () ->\r
+    valid = true\r
+    $('form', $('#tabs-1')).map  ->\r
+      form_name = $(@).attr('data-form-name')\r
+      if form_name\r
+        if validate_panel($(@))\r
+        else\r
+          valid = false\r
+    invalid_elements = []\r
+    $('form', $('#tabs-2')).map  ->\r
+      form_name = $(@).attr('data-form-name')\r
+      if form_name\r
+        if validate_element($(@))\r
+        else\r
+          valid = false\r
+          invalid_elements.push form_name\r
+    if invalid_elements.length > 0\r
+      bc = '#ef29ef'\r
+    else\r
+      bc = ''\r
+    $('a', $('#tabs-2-tab')).map ->\r
+      $(@).css('background-color', bc)\r
+    return valid\r
+  $('form').map  ->\r
+    form_name = $(@).attr('data-form-name')\r
+    if form_name\r
+      form = $(this)\r
+      set_validates(form)\r
   $('.panel-editor').map ->\r
     if $(@).attr('current') and parseInt($(@).attr('current')) > 0\r
       editor.pettanr_current_panel_id = parseInt($(@).attr('panel_id'))\r
@@ -72,11 +160,7 @@ $ ->
           $(trace + 'tab_panel').css('display', 'none')\r
           $(trace + 'zsort').css('display', 'none')\r
           $(trace + 'tsort').css('display', 'none')\r
-          switch $(@).attr('element_type')\r
-            when 'panel_picture'\r
-              trace = trace + 'div'\r
-          $(trace).css('display', 'none')\r
-          \r
+          display_element($(@), false)\r
     \r
     $('#pettanr-panel-submit').focusin ->\r
       editor.refresh_attribute($('#pettanr-panel-json'))\r
@@ -421,6 +505,11 @@ $ ->
     \r
     $('.edit_panel' ).map ->\r
       if $(@).attr('jqform')\r
+        $(@).submit ->\r
+          if validate_forms()\r
+            true\r
+          else\r
+            false\r
       else\r
         $(@).submit ->\r
           false\r
@@ -443,4 +532,6 @@ $ ->
     $('.new-element').map ->\r
       $(@).click -> \r
         false\r
-    \r
+    j = JSON.stringify(window.configurations)\r
+    $('#pettanr-configurations').val(j)\r
+\r
index 24aef1f..35d1ecd 100644 (file)
@@ -39,6 +39,11 @@ class PettanrEditor
           return true\r
       else\r
         return false\r
+  @is_panel = (o) ->\r
+    if PettanrEditor.is_element(o)\r
+      return false\r
+    else\r
+      return true\r
   @is_element = (o) ->\r
     if o.attr('element_type')\r
       return true\r
index 74983c8..ea390d3 100644 (file)
@@ -16,6 +16,20 @@ div.md5 {
   text-align: left;
 }
 
+input.error {
+  border-width: 3px;
+  border-style:  solid;
+  border-color:   #ef29ef;
+}
+textarea.error {
+  border-style:  solid;
+  border-color:   #111;
+}
+select.error {
+  border-style:  solid;
+  border-color:   #111;
+}
+
 .sheet {
   position:    relative;
   overflow:    hidden;
@@ -34,6 +48,7 @@ div.md5 {
 .sheet_panel {
   position:    absolute;
 }
+
 .pettanr-comic-wrapper {
   margin:  1em auto;
 }
@@ -289,6 +304,8 @@ font-family : monospace;
 .ui-tabs .ui-tabs-nav li.ui-tabs-active {
     margin-bottom: 0.2em;
 }
+.element-tab {
+}
 .elements-tab {
   width: 100%;
    overflow: hidden;
@@ -333,3 +350,9 @@ font-family : monospace;
   clear: both;
 }
 
+.field {
+    float: left; 
+}
+.row_break {
+  clear: both;
+}
index 0f3fade..5c5b63a 100644 (file)
@@ -136,6 +136,21 @@ class ApplicationController < ActionController::Base
     export_from_provider(url)
   end
   
+    rescue_from Pettanr::NotWork, :with => :render_not_work
+    def render_not_work(exception = nil)
+      if exception
+        logger.info "Rendering , :: #{exception.message}"
+      end
+      respond_to do |format|
+        format.html { 
+          render :file => "#{Rails.root}/public/not_work.html", :layout => false
+        }
+        format.json { 
+          render :text => "400 Not work", :status => 400
+        }
+      end
+    end
+    
   if Rails.env == 'production'
     rescue_from ActiveRecord::RecordNotFound, :with => :render_404
     rescue_from ActiveRecord::Forbidden, :with => :render_403
index 139699c..e9456f9 100644 (file)
@@ -31,6 +31,7 @@ class GroundColorsController < ApplicationController
   end
   
   def new
+    raise Pettanr::NotWork unless @author.working_panel
     @panel = Panel.edit(@author.working_panel, @author)
     @ground_color = GroundColor.new :panel_id => @panel.id, :code => params[:code].to_i
     @ground_color.supply_default
@@ -51,6 +52,7 @@ class GroundColorsController < ApplicationController
   end
 
   def create
+    raise Pettanr::NotWork unless @author.working_panel
     @panel = Panel.edit(@author.working_panel, @author)
     
     @ground_color = GroundColor.new 
index 26c14b7..9cf4159 100644 (file)
@@ -31,6 +31,7 @@ class GroundPicturesController < ApplicationController
   end
   
   def new
+    raise Pettanr::NotWork unless @author.working_panel
     @picture = Picture.show params[:picture_id], @author
     raise ActiveRecord::Forbidden unless @picture.enable?
     @panel = Panel.edit(@author.working_panel, @author)
@@ -54,6 +55,7 @@ class GroundPicturesController < ApplicationController
   end
 
   def create
+    raise Pettanr::NotWork unless @author.working_panel
     @panel = Panel.edit(@author.working_panel, @author)
     
     @ground_picture = GroundPicture.new
index f093949..5a98947 100644 (file)
@@ -51,6 +51,7 @@ class PanelPicturesController < ApplicationController
   end
 
   def new
+    raise Pettanr::NotWork unless @author.working_panel
     @picture = Picture.show params[:picture_id], @author
     raise ActiveRecord::Forbidden unless @picture.enable?
     @panel = Panel.edit(@author.working_panel, @author)
@@ -74,6 +75,7 @@ class PanelPicturesController < ApplicationController
   end
 
   def create
+    raise Pettanr::NotWork unless @author.working_panel
     @panel = Panel.edit(@author.working_panel, @author)
     
     @panel_picture = PanelPicture.new 
index 03be3ac..bc5aea8 100644 (file)
@@ -50,6 +50,7 @@ class SpeechBalloonsController < ApplicationController
   end
 
   def new
+    raise Pettanr::NotWork unless @author.working_panel
     @speech_balloon_template = SpeechBalloonTemplate.show params[:speech_balloon_template_id], @author
     
     @panel = Panel.edit(@author.working_panel, @author)
@@ -82,6 +83,7 @@ class SpeechBalloonsController < ApplicationController
   end
 
   def create
+    raise Pettanr::NotWork unless @author.working_panel
     SpeechBalloon.fold_extend_settings params
     @panel = Panel.edit(@author.working_panel, @author)
     @speech_balloon = SpeechBalloon.new 
index c5a6899..2ad8c17 100644 (file)
@@ -83,4 +83,1427 @@ module ApplicationHelper
     }.join("\n")
   end
   
+  def configurations
+    JSON.parse(<<HD
+{
+    "models": {
+        "Panel": "panel",
+        "panel": {
+            "class_name": "Panel",
+            "table_name": "panels",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "width": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "height": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "border": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {
+                    }
+                },
+                "publish": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "author_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "PanelPicture": "panel_picture",
+        "panel_picture": {
+            "class_name": "PanelPicture",
+            "table_name": "panel_pictures",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "panel_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "picture_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "x": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "y": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "width": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "height": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "link": {
+                    "type": "text",
+                    "rules": {
+                        "url": true
+                    }
+                },
+                "z": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "t": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "SpeechBalloon": "speech_balloon",
+        "speech_balloon": {
+            "class_name": "SpeechBalloon",
+            "table_name": "speech_balloons",
+            "extend": "classname",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "panel_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "speech_balloon_template_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "classname": {
+                    "type": "text",
+                    "rules": {
+                        "required": true
+                    }
+                },
+                "z": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "t": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "settings": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "Balloon": "balloon",
+        "balloon": {
+            "class_name": "Balloon",
+            "table_name": "balloons",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "speech_balloon_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "system_picture_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "x": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "y": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "width": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "height": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "r": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "settings": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "Speech": "speech",
+        "speech": {
+            "class_name": "Speech",
+            "table_name": "speeches",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "speech_balloon_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "writing_format_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "content": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "font_size": {
+                    "type": "float",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "text_align": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "range": [
+                            0,
+                            3
+                        ]
+                    }
+                },
+                "fore_color": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "range": [
+                            0,
+                            16777215
+                        ]
+                    }
+                },
+                "x": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "y": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "width": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "height": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "quotes": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "settings": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "GroundPicture": "ground_picture",
+        "ground_picture": {
+            "class_name": "GroundPicture",
+            "table_name": "ground_pictures",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "panel_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "picture_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "repeat": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "range": [
+                            0,
+                            3
+                        ]
+                    }
+                },
+                "x": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "y": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "z": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "t": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "GroundColor": "ground_color",
+        "ground_color": {
+            "class_name": "GroundColor",
+            "table_name": "ground_colors",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "panel_id": {
+                    "type": "number",
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {}
+                },
+                "code": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "range": [
+                            0,
+                            16777215
+                        ]
+                    }
+                },
+                "z": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 1
+                    }
+                },
+                "t": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true,
+                        "min": 0
+                    }
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        },
+        "WritingFormat": "writing_format",
+        "writing_format": {
+            "class_name": "WritingFormat",
+            "table_name": "writing_formats",
+            "attributes": {
+                "id": {
+                    "type": "number",
+                    "primary_key": 1,
+                    "rules": {
+                        "number": true
+                    }
+                },
+                "name": {
+                    "type": "text",
+                    "rules": {
+                        "required": true
+                    }
+                },
+                "classname": {
+                    "type": "text",
+                    "rules": {
+                        "required": true
+                    }
+                },
+                "caption": {
+                    "type": "text",
+                    "rules": {
+                        "required": true
+                    }
+                },
+                "system_picture_id": {
+                    "type": "number",
+                    "rules": {
+                        "required": true,
+                        "number": true
+                    }
+                },
+                "settings": {
+                    "type": "text",
+                    "rules": {
+                        "required": true
+                    }
+                },
+                "created_at": {
+                    "type": "datetime"
+                },
+                "updated_at": {
+                    "type": "datetime"
+                }
+            }
+        }
+    },
+    "elements": [
+        {
+            "name": "panel_picture",
+            "path_name": "panel_pictures",
+            "parts": []
+        },
+        {
+            "name": "speech_balloon",
+            "path_name": "circle_speech_balloon/speech_balloons",
+            "parts": [
+                "balloon",
+                "speech"
+            ]
+        },
+        {
+            "name": "ground_picture",
+            "path_name": "ground_pictures",
+            "parts": []
+        },
+        {
+            "name": "ground_color",
+            "path_name": "ground_colors",
+            "parts": []
+        }
+    ],
+    "forms": {
+        "Panel": "panel",
+        "panel": {
+            "attributes": {
+                "caption": {
+                    "column": "caption",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "width": {
+                    "column": "width",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "height": {
+                    "column": "height",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "border": {
+                    "column": "border",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "publish": {
+                    "column": "publish",
+                    "type": "select",
+                    "label": {},
+                    "options": {
+                        "source": "magic_number",
+                        "key": "comic_visible_items",
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "id": {
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "author_id": {
+                    "column": "author_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "caption",
+                "width",
+                "height",
+                "border",
+                "publish",
+                "id",
+                "author_id"
+            ]
+        },
+        "PanelPicture": "panel_picture",
+        "panel_picture": {
+            "attributes": {
+                "caption": {
+                    "column": "caption",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "x": {
+                    "column": "x",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "y": {
+                    "column": "y",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "width": {
+                    "column": "width",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    },
+                    "helpers": {
+                        "size": {
+                            "path": "panels/size_helper",
+                            "options": {
+                                "class": "panel_picture_width_tool"
+                            }
+                        }
+                    }
+                },
+                "height": {
+                    "column": "height",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    },
+                    "helpers": {
+                        "size": {
+                            "path": "panels/size_helper",
+                            "options": {
+                                "class": "panel_picture_height_tool"
+                            }
+                        }
+                    }
+                },
+                "link": {
+                    "column": "link",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "id": {
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "panel_id": {
+                    "column": "panel_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "picture_id": {
+                    "column": "picture_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "z": {
+                    "column": "z",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "t": {
+                    "column": "t",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "caption",
+                "x",
+                "y",
+                "width",
+                "height",
+                "link",
+                "id",
+                "panel_id",
+                "picture_id",
+                "z",
+                "t"
+            ]
+        },
+        "speech_balloon": {
+            "attributes": {
+                "speech_balloon.id": {
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.panel_id": {
+                    "column": "panel_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.speech_balloon_template_id": {
+                    "column": "speech_balloon_template_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.caption": {
+                    "column": "caption",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "speech_balloon.z": {
+                    "column": "z",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.t": {
+                    "column": "t",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.classname": {
+                    "column": "classname",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech_balloon.settings": {
+                    "column": "settings",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "balloon.id": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "balloon.speech_balloon_id": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "speech_balloon_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "balloon.system_picture_id": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "system_picture_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "balloon.r": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "r",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    },
+                    "helpers": {
+                        "tail_angle": {
+                            "path": "panels/tail_angle_helper",
+                            "options": {}
+                        }
+                    }
+                },
+                "balloon.x": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "x",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "balloon.y": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "y",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "balloon.width": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "width",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "balloon.height": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "height",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "balloon.settings": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "settings",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.id": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.speech_balloon_id": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "speech_balloon_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.x": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "x",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.y": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "y",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.width": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "width",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.height": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "height",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "speech.writing_format_id": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "writing_format_id",
+                    "type": "select",
+                    "label": {},
+                    "options": {
+                        "source": "model",
+                        "model": "writing_format",
+                        "method": "enable_list",
+                        "caption": "caption"
+                    }
+                },
+                "speech.font_size": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "font_size",
+                    "type": "select",
+                    "label": {},
+                    "options": {
+                        "source": "magic_number",
+                        "key": "speech_font_size_items",
+                        "row_break": true
+                    }
+                },
+                "speech.text_align": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "text_align",
+                    "type": "select",
+                    "label": {},
+                    "options": {
+                        "source": "magic_number",
+                        "key": "speech_text_align_items"
+                    }
+                },
+                "speech.quotes": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "quotes",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "speech.content": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "content",
+                    "type": "text_area",
+                    "label": {
+                        "row_break": true
+                    },
+                    "options": {
+                        "size": "45x5"
+                    }
+                },
+                "speech.fore_color": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "fore_color",
+                    "type": "hidden",
+                    "label": {
+                        "row_break": true
+                    },
+                    "options": {},
+                    "helpers": {
+                        "color": {
+                            "path": "panels/color_helper",
+                            "options": {},
+                            "wrapper": "speech-fore_color-wrap"
+                        }
+                    }
+                },
+                "speech.settings": {
+                    "model": "speech",
+                    "part": "speech",
+                    "column": "settings",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            }
+        },
+        "CircleSpeechBalloon": "circle_speech_balloon",
+        "circle_speech_balloon": {
+            "base": "speech_balloon",
+            "attributes": {},
+            "fields": [
+                "speech_balloon.caption",
+                "balloon.r",
+                "balloon.x",
+                "balloon.y",
+                "balloon.width",
+                "balloon.height",
+                "balloon.id",
+                "balloon.speech_balloon_id",
+                "balloon.system_picture_id",
+                "balloon.settings",
+                "speech.writing_format_id",
+                "speech.font_size",
+                "speech.text_align",
+                "speech.quotes",
+                "speech.content",
+                "speech.fore_color",
+                "speech.id",
+                "speech.speech_balloon_id",
+                "speech.x",
+                "speech.y",
+                "speech.width",
+                "speech.height",
+                "speech.settings",
+                "speech_balloon.id",
+                "speech_balloon.panel_id",
+                "speech_balloon.speech_balloon_template_id",
+                "speech_balloon.classname",
+                "speech_balloon.z",
+                "speech_balloon.t",
+                "speech_balloon.settings"
+            ]
+        },
+        "PlainSpeechBalloon": "plain_speech_balloon",
+        "plain_speech_balloon": {
+            "base": "speech_balloon",
+            "attributes": {
+                "balloon.r": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "r",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "speech_balloon.caption",
+                "balloon.r",
+                "balloon.x",
+                "balloon.y",
+                "balloon.width",
+                "balloon.height",
+                "balloon.id",
+                "balloon.speech_balloon_id",
+                "balloon.system_picture_id",
+                "balloon.settings",
+                "speech.writing_format_id",
+                "speech.font_size",
+                "speech.text_align",
+                "speech.quotes",
+                "speech.content",
+                "speech.fore_color",
+                "speech.id",
+                "speech.speech_balloon_id",
+                "speech.x",
+                "speech.y",
+                "speech.width",
+                "speech.height",
+                "speech.settings",
+                "speech_balloon.id",
+                "speech_balloon.panel_id",
+                "speech_balloon.speech_balloon_template_id",
+                "speech_balloon.classname",
+                "speech_balloon.z",
+                "speech_balloon.t",
+                "speech_balloon.settings"
+            ]
+        },
+        "SquareSpeechBalloon": "square_speech_balloon",
+        "square_speech_balloon": {
+            "base": "speech_balloon",
+            "attributes": {
+                "balloon.r": {
+                    "model": "balloon",
+                    "part": "balloon",
+                    "column": "r",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "speech_balloon.caption",
+                "balloon.r",
+                "balloon.x",
+                "balloon.y",
+                "balloon.width",
+                "balloon.height",
+                "balloon.id",
+                "balloon.speech_balloon_id",
+                "balloon.system_picture_id",
+                "balloon.settings",
+                "speech.writing_format_id",
+                "speech.font_size",
+                "speech.text_align",
+                "speech.quotes",
+                "speech.content",
+                "speech.fore_color",
+                "speech.id",
+                "speech.speech_balloon_id",
+                "speech.x",
+                "speech.y",
+                "speech.width",
+                "speech.height",
+                "speech.settings",
+                "speech_balloon.id",
+                "speech_balloon.panel_id",
+                "speech_balloon.speech_balloon_template_id",
+                "speech_balloon.classname",
+                "speech_balloon.z",
+                "speech_balloon.t",
+                "speech_balloon.settings"
+            ]
+        },
+        "GroundPicture": "ground_picture",
+        "ground_picture": {
+            "attributes": {
+                "id": {
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "panel_id": {
+                    "column": "panel_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "picture_id": {
+                    "column": "picture_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "caption": {
+                    "column": "caption",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "repeat": {
+                    "column": "repeat",
+                    "type": "select",
+                    "label": {},
+                    "options": {
+                        "source": "magic_number",
+                        "key": "ground_picture_repeat_items",
+                        "row_break": true
+                    }
+                },
+                "x": {
+                    "column": "x",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5
+                    }
+                },
+                "y": {
+                    "column": "y",
+                    "type": "number",
+                    "label": {},
+                    "options": {
+                        "size": 5,
+                        "row_break": true
+                    }
+                },
+                "z": {
+                    "column": "z",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "t": {
+                    "column": "t",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "caption",
+                "repeat",
+                "x",
+                "y",
+                "z",
+                "t",
+                "id",
+                "panel_id",
+                "picture_id"
+            ]
+        },
+        "GroundColor": "ground_color",
+        "ground_color": {
+            "attributes": {
+                "id": {
+                    "column": "id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "panel_id": {
+                    "column": "panel_id",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "caption": {
+                    "column": "caption",
+                    "type": "text",
+                    "label": {},
+                    "options": {
+                        "row_break": true
+                    }
+                },
+                "code": {
+                    "column": "code",
+                    "type": "hidden",
+                    "label": {
+                        "row_break": true
+                    },
+                    "options": {
+                        "row_break": true
+                    },
+                    "helpers": {
+                        "color": {
+                            "path": "panels/color_helper",
+                            "options": {},
+                            "wrapper": "ground_color-code-wrap"
+                        }
+                    }
+                },
+                "z": {
+                    "column": "z",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                },
+                "t": {
+                    "column": "t",
+                    "type": "hidden",
+                    "label": {
+                        "type": "hidden"
+                    },
+                    "options": {}
+                }
+            },
+            "fields": [
+                "id",
+                "panel_id",
+                "caption",
+                "code",
+                "z",
+                "t"
+            ]
+        }
+    },
+    "locales": {
+        "ja": {}
+    }
+}
+HD
+)
+  end
 end
index 49e6dcf..cc1dc82 100644 (file)
@@ -15,9 +15,6 @@ class Panel < ActiveRecord::Base
   validates :width, :presence => true, :numericality => true, :natural_number => true
   validates :height, :presence => true, :numericality => true, :natural_number => true
   validates :border, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
-  validates :x, :numericality => {:allow_blank => true}
-  validates :y, :numericality => {:allow_blank => true}
-  validates :z, :numericality => {:allow_blank => true, :greater_than => 0}
   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
   validates :publish, :presence => true, :numericality => true
   
@@ -86,8 +83,8 @@ class Panel < ActiveRecord::Base
     self.publish > 0
   end
   
-  def tag_id
-    'panel' + self.tag_panel_id
+  def tag_id c = nil
+    'panel' + self.tag_panel_id + c.to_s
   end
   
   def tag_panel_id
@@ -98,6 +95,34 @@ class Panel < ActiveRecord::Base
     self.tag_id + f.to_s
   end
   
+  def tag_attributes column = nil, opt = {}
+    {
+      :id => self.field_tag_id(column), :panel_id => self.tag_panel_id
+    }.merge(opt)
+  end
+  
+  def select_tag_attributes(selected, column, opt = {})
+    [
+      :last, :first, 
+      {:html => {:selected => selected}}, 
+      self.field_tag_attributes(column, opt)
+    ]
+  end
+  
+  def field_tag_attributes column, opt = {}
+    self.tag_attributes(column).merge(
+      {:column => column}
+    ).merge(opt)
+  end
+  
+  def tag_attr column = nil, opt = {}
+    self.tag_attributes(column, opt).to_attr
+  end
+  
+  def field_tag_attr column, no_attr, opt = {}
+    self.field_tag_attributes(column, no_attr, opt).to_attr
+  end
+  
   def self.default_page_size
     25
   end
index 06e1881..7877283 100644 (file)
@@ -47,6 +47,10 @@ class SpeechBalloon < ActiveRecord::Base
     false
   end
   
+  def extend_column
+    'classname'
+  end
+  
   def supply_default
     if self.panel
       self.t = self.panel.new_t 
index 84b983c..5d9ce6a 100644 (file)
@@ -5,18 +5,26 @@
     <%= f.label :title %><br />
     <%= f.text_field :title %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :description %><br />
     <%= f.text_area :description %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :visible %><br />
     <%= f.collection_select :visible, t_select_items(MagicNumber['comic_visible_items']), :last, :first, :html => {:selected => @comic.visible} %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :author_id %><br />
     <%= h @author.name %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="actions">
     <%= f.submit %>
   </div>
index a42714d..3d58ef2 100644 (file)
@@ -5,6 +5,8 @@
     <%= f.label :caption %>
     <%= f.text_field :caption, elm.field_tag_attributes(:caption, no_attr) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :code %>
     <%= f.text_field :code, elm.field_tag_attributes(:code, no_attr, :size => 8) %>
       </div>
    <% end %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :z %>
     <%= f.number_field :z, elm.field_tag_attributes(:z, no_attr, :size => 5) %>
-
+  </div>
+  <div class="row_break">
+  </div>
+  <div class="field">
     <%= f.label :t %>
     <%= f.number_field :t, elm.field_tag_attributes(:t, no_attr, :size => 5) %>
   </div>
index 5422d57..206993e 100644 (file)
@@ -5,21 +5,33 @@
     <%= f.label :caption %>
     <%= f.text_field :caption, elm.field_tag_attributes(:caption, no_attr) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :repeat %>
     <%= f.collection_select :repeat, t_select_items(MagicNumber['ground_picture_repeat_items']), *elm.select_tag_attributes(elm.repeat, :repeat, no_attr) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :x %>
     <%= f.number_field :x, elm.field_tag_attributes(:x, no_attr, :size => 5) %>
-
+  </div>
+  <div class="row_break">
+  </div>
+  <div class="field">
     <%= f.label :y %>
     <%= f.number_field :y, elm.field_tag_attributes(:y, no_attr, :size => 5) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :z %>
     <%= f.number_field :z, elm.field_tag_attributes(:z, no_attr, :size => 5) %>
-
+  </div>
+  <div class="row_break">
+  </div>
+  <div class="field">
     <%= f.label :t %>
     <%= f.number_field :t, elm.field_tag_attributes(:t, no_attr, :size => 5) %>
   </div>
index 345ca40..2c6dd4e 100644 (file)
@@ -1,34 +1,41 @@
 <h1><%= t '.title' -%></h1>
-
 <h2><%= link_to h(@author.name), main_app.author_path(@author) -%></h2>
 <h3><%= t('.updated_scroll') -%></h3>
 <table>
   <tr height="100px">
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('Scroll'), '/home/scrolls' %>
+      <%= link_to t('*'), new_scroll_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('ScrollPanel'), '/home/scroll_panels' %>
+      <%= link_to t('*'), new_scroll_panel_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('Comic'), '/home/comics' %>
+      <%= link_to t('*'), new_comic_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('Story'), '/home/stories' %>
+      <%= link_to t('*'), new_story_path %>
     </td>
   </tr>
   <tr height="100px">
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('StorySheet'), '/home/story_sheets' %>
+      <%= link_to t('*'), new_story_sheet_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('Sheet'), '/home/sheets' %>
+      <%= link_to t('*'), new_sheet_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('SheetPanel'), '/home/sheet_panels' %>
+      <%= link_to t('*'), new_sheet_panel_path %>
     </td>
     <td width="200px" align="center" valign="middle">
       <%= link_to t_m('Panel'), '/home/panels' %>
+      <%= link_to t('*'), new_panel_path %>
     </td>
   </tr>
 </table>
@@ -58,6 +65,7 @@
     <tr height="100px">
       <td width="200px" align="center" valign="middle">
         <%= link_to t_m('OriginalPicture'), main_app.original_pictures_path %>
+        <%= link_to t('*'), new_original_picture_path %>
       </td>
       <td width="200px" align="center" valign="middle">
         <%= link_to t_m('ResourcePicture'), '/home/resource_pictures' %>
index 6e89624..5236cfd 100644 (file)
   <div width="100%" style="background-color: #fadddd; padding: 5px;">\r
     <%= link_to t('tab.creator.home'), '/home' %>\r
     <%= link_to t('tab.creator.comic'), '/home/comics' %>\r
+    <%= link_to t('*'), new_comic_path %>\r
     <%= link_to t('tab.creator.story'), '/home/stories' %>\r
     <%= link_to t('tab.creator.sheet'), '/home/sheets' %>\r
+    <%= link_to t('*'), new_sheet_path %>\r
     <%= link_to t('tab.creator.scroll'), '/home/scrolls' %>\r
+    <%= link_to t('*'), new_scroll_path %>\r
     <%= link_to t('tab.creator.panel'), '/home/panels' %>\r
+    <%= link_to t('*'), new_panel_path %>\r
     <% if @artist %>\r
       <%= link_to t('tab.creator.original_picture'), main_app.original_pictures_path %>\r
+      <%= link_to t('*'), new_original_picture_path %>\r
       <%= link_to t('tab.creator.resource_picture'), '/home/resource_pictures' %>\r
     <% end %>\r
     <% if @author and @author.working? -%>\r
index e0c7047..ee4fd84 100644 (file)
@@ -5,20 +5,32 @@
     <%= f.label :caption %>
     <%= f.text_field :caption, elm.field_tag_attributes(:caption, no_attr) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :x %>
     <%= f.number_field :x, elm.field_tag_attributes(:x, no_attr, :size => 5) %>
-
+  </div>
+  <div class="row_break">
+  </div>
+  <div class="field">
     <%= f.label :y %>
     <%= f.number_field :y, elm.field_tag_attributes(:y, no_attr, :size => 5) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :z %>
     <%= f.number_field :z, elm.field_tag_attributes(:z, no_attr, :size => 5) %>
-
+  </div>
+  <div class="row_break">
+  </div>
+  <div class="field">
     <%= f.label :t %>
     <%= f.number_field :t, elm.field_tag_attributes(:t, no_attr, :size => 5) %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :width %>
     <%= f.number_field :width, elm.field_tag_attributes(:width, no_attr, :size => 5) %>
@@ -26,6 +38,8 @@
       <%= render elm.form_helper_template(:width), :elm => elm, :no_attr => no_attr, :opt => {:class => "panel_picture_width_tool"} %>
     <% end %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :height %>
     <%= f.number_field :height, elm.field_tag_attributes(:height, no_attr, :size => 5) %>
@@ -33,6 +47,8 @@
       <%= render elm.form_helper_template(:height), :elm => elm, :no_attr => no_attr, :opt => {:class => "panel_picture_height_tool"} %>
     <% end %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :link %>
     <%= f.text_field :link, elm.field_tag_attributes(:link, no_attr) %>
diff --git a/app/views/panels/_element_form.html.erb b/app/views/panels/_element_form.html.erb
new file mode 100644 (file)
index 0000000..24d4966
--- /dev/null
@@ -0,0 +1,87 @@
+<% element_name = elm.element_name %>
+<% extend_element_name = elm.extend_element_name %>
+<% form_configurations = elm.find_configurations @configurations['forms'], extend_element_name %>
+<% base_attributes = if form_configurations['base'] %>
+  <% @configurations['forms'][form_configurations['base']]['attributes'] %>
+<% else %>
+  <% {} %>
+<% end %>
+<% extend_attributes = form_configurations['attributes'] || {} %>
+<% form_attributes = base_attributes.merge(extend_attributes) %>
+<% form_model_name = form_configurations['model'] || form_configurations['base'] || element_name %>
+<%= form_for(elm, :html => elm.tag_attributes('form', 'data-form-name' => extend_element_name)) do |f| %>
+  <% form_configurations['fields'].each do |field_name| %>
+    <% field_configurations = form_attributes[field_name] || {} %>
+    <% field_model_name = field_configurations['model'] || form_model_name %>
+    <% model_configurations =  @configurations['models'][field_model_name] %>
+    <% column = field_configurations['column'] %>
+    <% model_configurations['attributes'] %>
+    <% primary_key = model_configurations['attributes'][column]['primary_key'] %>
+    
+    <% next if primary_key and elm.new_record? %>
+    
+    <% options = field_configurations['options'] || {} %>
+    <% opt = {} %>
+    <% opt.merge!('data-model' => field_model_name) %>
+    <% field_element = if field_configurations['part'] %>
+      <% elm.__send__ field_configurations['part'] %>
+    <% else %>
+      <% elm %>
+    <% end %>
+    <% name = if field_configurations['part'] %>
+      <% form_model_name + '[' + field_model_name + '_attributes][' + column + ']' %>
+    <% else %>
+      <% form_model_name + '[' + column + ']' %>
+    <% end %>
+    <div class="field">
+      <% label = field_configurations['label'] || {}  %>
+      <% if label['type'] and label['type'] == 'hidden' %>
+      <% else %>
+        <%= t 'activerecord.attributes.' + field_model_name + '.' +  column %>
+      <% end %>
+      <% if label['row_break'] %>
+        <br>
+      <% end %>
+      <% case field_configurations['type'] %>
+      <% when 'text' %>
+        <% opt['size'] = field_configurations['options']['size'] if field_configurations['options']['size'] %>
+        <%= text_field_tag name, field_element.attributes[column], field_element.field_tag_attributes(column, no_attr, opt) %>
+      <% when 'text_area' %>
+        <% opt['size'] = field_configurations['options']['size'] if field_configurations['options']['size'] %>
+        <%= text_area_tag name, field_element.attributes[column], field_element.field_tag_attributes(column, no_attr, opt) %>
+      <% when 'number' %>
+        <% opt['size'] = field_configurations['options']['size'] if field_configurations['options']['size'] %>
+        <%= number_field_tag name, field_element.attributes[column], field_element.field_tag_attributes(column, no_attr, opt) %>
+      <% when 'hidden' %>
+        <%= hidden_field_tag name, field_element.attributes[column], field_element.field_tag_attributes(column, no_attr, opt) %>
+      <% when 'select' %>
+        <% items = case options['source'] %>
+        <% when 'model' %>
+          <% select_model = options['model'] %>
+          <% select_class = @configurations['models'][select_model]['class_name'] %>
+          <% l = select_class.constantize.__send__ options['method'] %>
+          <% l.map {|i| [i.attributes[options['caption']], i.id] } %>
+        <% when 'magic_number' %>
+          <% t_select_items(MagicNumber[options['key']]) %>
+        <% else %>
+        <% end %>
+        <%= select_tag name, options_for_select(items, field_element.attributes[column]), field_element.field_tag_attributes(column, no_attr, opt) %>
+      <% end %>
+      <% if field_configurations['helpers'] %>
+        <% field_configurations['helpers'].each do |n, helper| %>
+          <% if helper['wrapper'] %>
+            <div class="<%= helper['wrapper'] -%>">
+          <% end %>
+          <%= render helper['path'], :elm => field_element, :no_attr => no_attr, :opt => helper['options'] %>
+          <% if helper['wrapper'] %>
+            </div>
+          <% end %>
+        <% end %>
+      <% end %>
+    </div>
+    <% if options['row_break'] %>
+      <div class="row_break">
+      </div>
+    <% end %>
+  <% end %>
+<% end %>
index 525e9e3..10de5b0 100644 (file)
@@ -1,8 +1,8 @@
-<li id="<%= elm.field_tag_id(:element_tab) -%>" panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+<li class="element_tab" <%= raw elm.tag_attr(:element_tab) -%>>
   <a href="#elements-tabs-<%= elm.t -%>">
     <div class="elements-tab">
       <%= render elm.element_face_template, :elm => elm %>
     </div>
   </a>
-  <button class="ui-icon-destroy" id="<%= elm.field_tag_id(:_destroy_button) -%>" panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>"></button>
+  <button class="ui-icon-destroy" <%= raw elm.tag_attr(:_destroy_button) -%>></button>
 </li>
index 59768b9..67217dc 100644 (file)
@@ -1,35 +1,44 @@
+<% @configurations = configurations %>
 <div id="tabs" class="panel-editor" panel_id="<%= @panel.tag_panel_id -%>" current="1">
   <ul>
-    <li><a href="#tabs-1">panel</a></li>
-    <li><a href="#tabs-2">elements</a></li>
-    <li><a href="#tabs-3">t order</a></li>
-    <li><a href="#tabs-4">z order</a></li>
-    <li><a href="#tabs-5">new</a></li>
+    <li id="tabs-1-tab"><a href="#tabs-1">panel</a></li>
+    <li id="tabs-2-tab"><a href="#tabs-2">elements</a></li>
+    <li id="tabs-3-tab"><a href="#tabs-3">t order</a></li>
+    <li id="tabs-4-tab"><a href="#tabs-4">z order</a></li>
+    <li id="tabs-5-tab"><a href="#tabs-5">new</a></li>
   </ul>
   <div id="tabs-1">
-    <%= form_for(@panel) do |f| %>
+    <%= form_for(@panel, :html => {:id => @panel.tag_id('form'), 'data-form-name' => 'panel'}) do |f| %>
       <%= render 'system/error_explanation', :obj => @panel %>
 
       <div class="field">
         <%= f.label :caption %>
-        <%= f.text_field :caption, :id => @panel.field_tag_id(:caption), :panel_id => @panel.tag_panel_id, :column => :caption -%>
+        <%= f.text_field :caption, @panel.field_tag_attributes(:caption, 'data-model' => 'panel') -%>
+      </div>
+      <div class="row_break">
       </div>
       <div class="field">
         <%= f.label :width %>
-        <%= f.number_field :width, :size => 5, :id => @panel.field_tag_id(:width), :panel_id => @panel.tag_panel_id, :column => :width %>
-
+        <%= f.number_field :width, @panel.field_tag_attributes(:width, :size => 5, 'data-model' => 'panel') %>
+      </div>
+      <div class="field">
         <%= f.label :height %>
-        <%= f.number_field :height, :size => 5, :id => @panel.field_tag_id(:height), :panel_id => @panel.tag_panel_id, :column => :height %>
-
+        <%= f.number_field :height, @panel.field_tag_attributes(:height, :size => 5, 'data-model' => 'panel') %>
+      </div>
+      <div class="row_break">
+      </div>
+      <div class="field">
         <%= f.label :border %>
-        <%= f.number_field :border, :size => 5, :id => @panel.field_tag_id(:border), :panel_id => @panel.tag_panel_id, :column => :border %>
+        <%= f.number_field :border, @panel.field_tag_attributes(:border, :size => 5, 'data-model' => 'panel') %>
       </div>
       <div class="field">
         <%= f.label :publish %>
-        <%= f.collection_select :publish, t_select_items(MagicNumber['panel_visible_items']), :last, :first, {:html => {:selected => @panel.publish}}, {:id => @panel.field_tag_id(:publish), :panel_id => @panel.tag_panel_id, :column => :publish} %>
+        <%= f.collection_select :publish, t_select_items(MagicNumber['panel_visible_items']), *@panel.select_tag_attributes(@panel.publish, :publish, 'data-model' => 'panel') %>
+      </div>
+      <div class="row_break">
       </div>
       <% unless @panel.new_record?  %>
-        <%= f.hidden_field :id, :id => @panel.field_tag_id(:id), :panel_id => @panel.tag_panel_id, :column => :id %>
+        <%= f.hidden_field :id, @panel.field_tag_attributes(:id, 'data-model' => 'panel') %>
       <% end %>
       <div class="actions">
         <%= f.submit 'panels.submit', :class => "submit" %>
         <% end %>
       </ul>
       <% @panel.panel_elements.each do |elm| %>
-        <div id="<%= elm.field_tag_id(:tab_panel) -%>" panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+        <div <%= raw elm.tag_attr(:tab_panel) -%>>
           <div id="elements-tabs-<%= elm.t -%>">
-            <%= render elm.form_template, :elm => elm, :no_attr => 0 %>
-            <%= hidden_field_tag '_destroy', '', :id => elm.field_tag_id(:_destroy), :panel_id => elm.tag_panel_id, :element_id => elm.tag_element_id, :element_type => elm.tag_element_type, :column => :_destroy %>
+            <%= render 'element_form', :elm => elm, :no_attr => 0 %>
+            <%= hidden_field_tag '_destroy', '', elm.field_tag_attributes(:_destroy, 0) %>
           </div>
         </div>
       <% end %>
@@ -55,9 +64,9 @@
   </div>
   <div id="tabs-3">
     <div class="tsort-box">
-      <ul id="<%= @panel.tag_id -%>tsort" class="tsort tsort-tabs-nav" panel_id="<%= @panel.tag_panel_id -%>">
+      <ul class="tsort tsort-tabs-nav" <%= raw @panel.tag_attr(:tsort) -%>>
         <% @panel.panel_elements.each do |elm| %>
-          <li id="<%= elm.field_tag_id(:tsort) -%>" panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+          <li <%= raw elm.tag_attr(:tsort) -%>>
             <div class="elements-tab">
               <%= render elm.path_name + '/element_face', :elm => elm %>
             </div>
@@ -65,9 +74,9 @@
         <% end %>
       </ul>
     </div>
-    <div id="<%= @panel.tag_id -%>scenario" class="scenario" panel_id="<%= @panel.tag_panel_id -%>">
+    <div class="scenario" <%= raw @panel.tag_attr(:scenario) -%>>
       <% @panel.panel_elements.each do |elm| %>
-        <div panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+        <div <%= raw elm.tag_attr() -%>>
           <%= render elm.scenario_template, :elm => elm, :no_attr => 0 %>
         </div>
       <% end %>
@@ -77,9 +86,9 @@
   </div>
   <div id="tabs-4">
     <div class="zsort-box">
-      <ul id="<%= @panel.tag_id -%>zsort" class="zsort zsort-tabs-nav" panel_id="<%= @panel.tag_panel_id -%>">
+      <ul class="zsort zsort-tabs-nav" <%= raw @panel.tag_attr(:zsort) -%>>
         <% @panel.zorderd_elements.each do |elm| %>
-          <li id="<%= elm.field_tag_id(:zsort) -%>" panel_id="<%= elm.tag_panel_id -%>" element_id="<%= elm.tag_element_id -%>" element_type="<%= elm.tag_element_type -%>">
+          <li <%= raw elm.tag_attr(:zsort) -%>>
             <div class="elements-tab">
               <%= render elm.class.to_s.tableize + '/element_face', :elm => elm %>
             </div>
     </div>
   <% end %>
 </div>
+  <%# text_field_tag "json", '', :id => 'pettanr-configurations' %>
index f27574a..864b0c0 100644 (file)
@@ -1 +1 @@
-<%= content_tag :span, '', elm.tag_attributes('', :class => opt[:class]) %>
+<%= content_tag :span, '', elm.tag_attributes('', :class => opt[:class] || opt['class']) %>
index f2f70ad..0cf77a8 100644 (file)
@@ -5,14 +5,20 @@
     <%= f.label :scroll_id %><br />
     <%= f.number_field :scroll_id %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :t %><br />
     <%= f.number_field :t %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :panel_id %><br />
     <%= f.number_field :panel_id %>
   </div>
+  <div class="row_break">
+  </div>
 
   <div class="actions">
     <%= f.submit %>
index dc72ec5..1d67f75 100644 (file)
@@ -2,4 +2,3 @@
 <p id="notice"><%= notice %></p>
 
 <%= render 'form' %>
-<%= button_to 'Destroy', @scroll_panel, confirm: 'Are you sure?', method: :delete %>
index 3ca23fb..d0a51d0 100644 (file)
@@ -5,18 +5,26 @@
     <%= f.label :title %><br />
     <%= f.text_field :title %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :description %><br />
     <%= f.text_area :description %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :visible %><br />
     <%= f.collection_select :visible, t_select_items(MagicNumber['scroll_visible_items']), :last, :first, :html => {:selected => @scroll.visible} %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :author_id %><br />
     <%= h @author.name %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="actions">
     <%= f.submit %>
   </div>
index 18320c4..8134fa8 100644 (file)
@@ -32,8 +32,8 @@
   <%= l @scroll.updated_at %>
 </p>
 
-<%= link_to t('link.edit'), edit_scroll_path(@scroll) %>
 <% if @scroll.own? @author -%>
+  <%= link_to t('link.edit'), edit_scroll_path(@scroll) %>
   <h3><%= t('scroll_panels.append.new_panels') -%></h3>
   <table>
     <% @new_panels.each do |panel| %>
index f1a438c..25dbd02 100644 (file)
@@ -31,6 +31,8 @@
       <%= f.number_field :y, elm.field_tag_attributes(:y, no_attr, :size => 5) %>
     <% end %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :z %>
     <% if elm.new_record? %>
@@ -46,6 +48,8 @@
       <%= f.number_field :t, elm.field_tag_attributes(:t, no_attr, :size => 5) %>
     <% end %>
   </div>
+  <div class="row_break">
+  </div>
 
   <% unless elm.new_record?  %>
     <%= f.hidden_field :id, elm.field_tag_attributes(:id, no_attr) %>
index 35aeb0c..fd3c9ef 100644 (file)
@@ -14,6 +14,8 @@
         <%= f.label :caption %>
         <%= f.text_field :caption, :id => @sheet.field_tag_id(:caption), :sheet_id => @sheet.tag_sheet_id, :column => :caption -%>
       </div>
+      <div class="row_break">
+      </div>
       <div class="field">
         <%= f.label :width %>
         <%= f.number_field :width, :size => 5, :id => @sheet.field_tag_id(:width), :sheet_id => @sheet.tag_sheet_id, :column => :width %>
         <%= f.number_field :height, :size => 5, :id => @sheet.field_tag_id(:height), :sheet_id => @sheet.tag_sheet_id, :column => :height %>
 
       </div>
+      <div class="row_break">
+      </div>
       <div class="field">
         <%= f.label :visible %>
         <%= f.collection_select :visible, t_select_items(MagicNumber['sheet_visible_items']), :last, :first, {:html => {:selected => @sheet.visible}}, {:id => @sheet.field_tag_id(:visible), :sheet_id => @sheet.tag_sheet_id, :column => :visible} %>
       </div>
+      <div class="row_break">
+      </div>
       <% unless @sheet.new_record?  %>
         <%= f.hidden_field :id, :id => @sheet.field_tag_id(:id), :sheet_id => @sheet.tag_sheet_id, :column => :id %>
       <% end %>
diff --git a/app/views/speech_balloons/_form.html.erb b/app/views/speech_balloons/_form.html.erb
deleted file mode 100644 (file)
index 6a3f3a6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<%= form_for(speech_balloon) do |f| %>
-  <%= render 'system/error_explanation', :obj => speech_balloon %>
-
-  <div class="field">
-    <%= f.label :caption %><br />
-    <%= f.number_field :caption, :id => speech_balloon.field_tag_id(:caption), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :caption, :tree => speech_balloon.field_tree(:caption) %>
-  </div>
-  <div class="field">
-    <%= f.label :z %><br />
-    <%= f.number_field :z, :id => speech_balloon.field_tag_id(:z), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :z, :tree => speech_balloon.field_tree(:z) %>
-  </div>
-  <div class="field">
-    <%= f.label :t %><br />
-    <%= f.number_field :t, :id => speech_balloon.field_tag_id(:t), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :t, :tree => speech_balloon.field_tree(:t) %>
-  </div>
-  
-  <%= f.fields_for(:balloon) do |bf| %>
-    <%= render 'balloons/form', :f => bf, :balloon => speech_balloon.balloon %>
-  <% end %>
-
-  <%= f.fields_for(:speech) do |sf| %>
-    <%= render 'speeches/form', :f => sf, :speech => speech_balloon.speech %>
-  <% end %>
-
-  <%= f.hidden_field :panel_id, :id => speech_balloon.field_tag_id(:panel_id), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :panel_id, :tree => speech_balloon.field_tree(:panel_id) %>
-  <%= f.hidden_field :classname, :id => speech_balloon.field_tag_id(:classname), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :classname, :tree => speech_balloon.field_tree(:classname) %>
-  <%= f.hidden_field :speech_balloon_template_id, :id => speech_balloon.field_tag_id(:speech_balloon_template_id), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :speech_balloon_template_id, :tree => speech_balloon.field_tree(:speech_balloon_template_id) %>
-  <% unless speech_balloon.new_record?  %>
-    <%= f.hidden_field :id, :id => speech_balloon.field_tag_id(:id), :panel_id => speech_balloon.tag_panel_id, :element_id => speech_balloon.tag_element_id, :element_type => speech_balloon.tag_element_type, :column => :id, :tree => speech_balloon.field_tree(:id) %>
-  <% end %>
-
-  <div class="actions">
-    <%= f.submit t('speech_balloons.submit'), :class => "submit" %>
-  </div>
-<% end %>
index 4355267..d5d80a4 100644 (file)
@@ -5,26 +5,38 @@
     <%= f.label :comic_id %><br />
     <%= f.number_field :comic_id %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :title %><br />
     <%= f.text_field :title %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :description %><br />
     <%= f.text_area :description %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :visible %><br />
     <%= f.collection_select :visible, t_select_items(MagicNumber['story_visible_items']), :last, :first, :html => {:selected => @story.visible} %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :author_id %><br />
     <%= h @author.name %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :t %><br />
     <%= f.number_field :t %>
   </div>
+  <div class="row_break">
+  </div>
 
   <div class="actions">
     <%= f.submit %>
index 601a0f9..3d8b075 100644 (file)
@@ -5,14 +5,20 @@
     <%= f.label :story_id %><br />
     <%= f.number_field :story_id %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :sheet_id %><br />
     <%= f.number_field :sheet_id %>
   </div>
+  <div class="row_break">
+  </div>
   <div class="field">
     <%= f.label :t %><br />
     <%= f.number_field :t %>
   </div>
+  <div class="row_break">
+  </div>
 
   <div class="actions">
     <%= f.submit %>
index 7e45d59..1d67f75 100644 (file)
@@ -2,4 +2,3 @@
 <p id="notice"><%= notice %></p>
 
 <%= render 'form' %>
-<%= button_to 'Destroy', @story_sheet, confirm: 'Are you sure?', method: :delete %>
index 3e62c61..8a2e303 100644 (file)
@@ -119,5 +119,7 @@ module Pettanr
   TestLayout = false
   class BadRequest < StandardError
   end
+  class NotWork < StandardError
+  end
 end
 
index fe977c8..37f9f54 100644 (file)
@@ -9,6 +9,9 @@ class CopyToScroll < ActiveRecord::Migration
     ::Story.find(:all).each do |i|
       attr = i.attributes
       attr.delete 'id'
+      attr.delete 'x'
+      attr.delete 'y'
+      attr.delete 'z'
       attr['scroll_id'] = attr['comic_id']
       attr.delete 'comic_id'
       ::ScrollPanel.create! attr
index dc9b2c6..a92f430 100644 (file)
@@ -48,6 +48,26 @@ module Element
       self.class.colum_structures[column_name] and self.class.colum_structures[column_name][:helper]
     end
     
+    def element_name
+      self.class.to_s.underscore
+    end
+    
+    def extend_column
+      nil
+    end
+    
+    def extend_element_name
+      self.extend_column ? self.attributes[extend_column] : self.element_name
+    end
+    
+    def find_configurations hash, key
+       if hash[key].is_a? String
+         self.find_configurations hash, hash[key]
+       else
+         return hash[key]
+       end
+    end
+    
     def new_index
       @new_index
     end
diff --git a/public/not_work.html b/public/not_work.html
new file mode 100644 (file)
index 0000000..5f8b3bd
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>コマをつかんでいません</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/404.html -->
+  <div class="dialog">
+    <h1>作業対象のコマが指定されていません。</h1>
+    <p>エレメントを新規作成するなど、一部の操作ではコマをつかんでおく必要があります。</p>
+  </div>
+</body>
+</html>
index 416fb17..20afa07 100644 (file)
@@ -31,9 +31,6 @@ describe Panel do
         @panel.width = 1\r
         @panel.height = 1\r
         @panel.border = 0\r
-        @panel.x = -99999\r
-        @panel.y = -99999\r
-        @panel.z = 1\r
         @panel.publish = 0\r
         @panel.should be_valid\r
       end\r
@@ -41,9 +38,6 @@ describe Panel do
         @panel.width = 99999\r
         @panel.height = 99999\r
         @panel.border = 99999\r
-        @panel.x = 99999\r
-        @panel.y = 99999\r
-        @panel.z = 99999\r
         @panel.publish = 99999\r
         @panel.should be_valid\r
       end\r
@@ -103,48 +97,6 @@ describe Panel do
         @panel.should be_valid\r
       end\r
     end\r
-    context 'xを検証するとき' do\r
-      it '数値でなければ失敗する' do\r
-        @panel.x = 'a'\r
-        @panel.should_not be_valid\r
-      end\r
-      it '0なら通る' do\r
-        @panel.x = '0'\r
-        @panel.should be_valid\r
-      end\r
-      it '負でも通る' do\r
-        @panel.x = -1\r
-        @panel.should be_valid\r
-      end\r
-    end\r
-    context 'yを検証するとき' do\r
-      it '数値でなければ失敗する' do\r
-        @panel.y = 'a'\r
-        @panel.should_not be_valid\r
-      end\r
-      it '0なら通る' do\r
-        @panel.y = '0'\r
-        @panel.should be_valid\r
-      end\r
-      it '負でも通る' do\r
-        @panel.y = -1\r
-        @panel.should be_valid\r
-      end\r
-    end\r
-    context 'zを検証するとき' do\r
-      it '数値でなければ失敗する' do\r
-        @panel.z = 'a'\r
-        @panel.should_not be_valid\r
-      end\r
-      it '0なら失敗する' do\r
-        @panel.z = '0'\r
-        @panel.should_not be_valid\r
-      end\r
-      it '負なら失敗する' do\r
-        @panel.z = -1\r
-        @panel.should_not be_valid\r
-      end\r
-    end\r
     context 'author_idを検証するとき' do\r
       it 'nullなら失敗する' do\r
         @panel.author_id = nil\r