first working version
author<mako@atdot.cc> <>
Fri, 14 Sep 2007 19:22:57 +0000 (15:22 -0400)
committer<mako@atdot.cc> <>
Fri, 14 Sep 2007 19:22:57 +0000 (15:22 -0400)
17 files changed:
ruler_web.py [deleted file]
static/images/bl.png [new file with mode: 0644]
static/images/br.png [new file with mode: 0644]
static/images/r.png [new file with mode: 0644]
static/images/tl.png [new file with mode: 0644]
static/images/tr.png [new file with mode: 0644]
static/images/trash.png [deleted file]
static/images/yourule_banner.png [new file with mode: 0644]
static/images/yourule_banner.svg [new file with mode: 0644]
static/style.css [new file with mode: 0644]
svgruler.py [moved from ruler.py with 97% similarity]
templates/_form_elements.tmpl
templates/gallery.tmpl
templates/index.tmpl
templates/show_ruler.tmpl
templates/site.tmpl
yourule.py [new file with mode: 0755]

diff --git a/ruler_web.py b/ruler_web.py
deleted file mode 100755 (executable)
index 2738f8f..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import division
-import web
-import sys, os, re
-from storm.locals import *
-from ruler import RulerImage
-
-# the url map for the application
-urls = ( '/', 'index',
-         '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
-         '/show/(.*(svg|png|jpg))', 'ruler',
-         '/gallery(.*)', 'gallery',
-         '/delete/(\d+)', 'delete',
-         '/undelete/(\d+)', 'undelete')
-
-database = create_database("sqlite:ruler_web.db")
-store = Store(database)
-
-class SavedRuler(object):
-    __storm_table__ = "gallery"
-    id = Int(primary=True)
-    pixel_width = Float()
-    unit_width = Float()
-    model = Unicode()
-    units = Unicode()
-    show = Int()
-
-    def __init__(self, **kw):
-        self.pixel_width = kw['pixel_width']
-        self.unit_width = kw['unit_width']
-        self.units = kw['units']
-        self.model = kw['model']
-
-    def cm_width(self):
-        if self.units == 'centimeters':
-            return self.unit_width
-        elif self.units == 'inches':
-            return(self.unit_width * 2.54)
-
-    def in_width(self):
-        if self.units == 'inches':
-            return self.unit_width
-        elif self.units == 'centimeters':
-            return(self.unit_width * 0.3937)
-
-
-class index:
-    def GET(self):
-        web.header("Content-Type","text/html; charset=utf-8")
-        web.render('index.tmpl')
-
-    def POST(self):
-        input = web.input()
-
-        pixel_width = input['pixel_width']
-        unit_width = input['unit_width']
-        units = input['units']
-        ruler_url = 'ruler_%spx_%s%s.png' % (pixel_width, unit_width, units)
-        web.redirect('/show/%s' % ruler_url)
-
-class ruler:
-    def GET(self, ruler_url, ext):
-        web.debug('test test')
-        if web.input().has_key('fromgallery'):
-            fromgallery = True
-        else:
-            fromgallery = False
-
-        other_unit, other_unit_url = get_other_units(ruler_url)
-
-        web.header("Content-Type","text/html; charset=utf-8")
-        web.render('show_ruler.tmpl')
-
-
-class ruler_img:
-    def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
-
-        # TODO check to see if it's a format that we support
-
-        # set ruler height to be 200 px always
-        pixel_width = float(pixel_width)
-        unit_width = float(unit_width)
-
-        ruler_height = 200
-
-        scale = pixel_width / unit_width
-        ruler_length = int(unit_width)
-
-        ruler = Ruler(scale, units, ruler_height, ruler_length)
-
-        # print the header
-        if ext == 'svg': ext = 'svg+xml'
-        web.header("Content-Type", "image/%s" % ext)
-
-        if ext == 'svg+xml':
-            sys.stdout.write(ruler.output())
-        else:
-            pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
-                                  (pixel_width, ruler_height, ext))
-
-            pin.write(ruler.output())
-            pin.close()
-            sys.stdout.write(pout.read())
-
-class gallery:
-    def GET(self, ruler_url):
-
-        if ruler_url:
-            pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
-
-        rulers = store.find(SavedRuler, SavedRuler.show == 1)
-        rulers.order_by(SavedRuler.model)
-
-        web.render('gallery.tmpl')
-
-    def POST(self):
-        input = web.input()
-
-        new_ruler = SavedRuler(pixel_width=float(input['pixel_width']),
-                               unit_width=float(input['unit_width']),
-                               units=unicode(input['units']),
-                               model=unicode(input['model']))
-
-        store.add(new_ruler)
-        store.commit()
-
-        web.redirect('gallery')
-
-class delete:
-    def GET(self, id):
-        ruler = store.get(SavedRuler, int(id))
-        ruler.show = 0
-        store.commit()
-        web.redirect('/gallery')
-
-
-class undelete:
-    def GET(self, id):
-        ruler = store.get(SavedRuler, int(id))
-        ruler.show = 1
-        store.commit()
-        web.redirect('/gallery')
-
-def get_other_units(url):
-    pixel_width, unit_width, units = process_ruler_url(url)[0:3]
-    ruler = SavedRuler(pixel_width=float(pixel_width),
-                       unit_width=float(unit_width),
-                       units=unicode(units),
-                       model=unicode(model))
-
-def process_ruler_url(url):
-    url = re.sub(r'^/?(ruler.*)$', r'\1', url)
-    return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
-           url).groups())
-
-# render the site template here so that i can use it later
-web.render('site.tmpl', None, True, 'site')
-
-web.webapi.internalerror = web.debugerror
-if __name__ == "__main__":
-    web.run(urls, globals(), web.reloader)
-
diff --git a/static/images/bl.png b/static/images/bl.png
new file mode 100644 (file)
index 0000000..f0970ae
Binary files /dev/null and b/static/images/bl.png differ
diff --git a/static/images/br.png b/static/images/br.png
new file mode 100644 (file)
index 0000000..7c1a5c8
Binary files /dev/null and b/static/images/br.png differ
diff --git a/static/images/r.png b/static/images/r.png
new file mode 100644 (file)
index 0000000..fab4ac0
Binary files /dev/null and b/static/images/r.png differ
diff --git a/static/images/tl.png b/static/images/tl.png
new file mode 100644 (file)
index 0000000..04576f8
Binary files /dev/null and b/static/images/tl.png differ
diff --git a/static/images/tr.png b/static/images/tr.png
new file mode 100644 (file)
index 0000000..e4ac949
Binary files /dev/null and b/static/images/tr.png differ
diff --git a/static/images/trash.png b/static/images/trash.png
deleted file mode 100644 (file)
index 0e0953c..0000000
Binary files a/static/images/trash.png and /dev/null differ
diff --git a/static/images/yourule_banner.png b/static/images/yourule_banner.png
new file mode 100644 (file)
index 0000000..877889c
Binary files /dev/null and b/static/images/yourule_banner.png differ
diff --git a/static/images/yourule_banner.svg b/static/images/yourule_banner.svg
new file mode 100644 (file)
index 0000000..3b46682
--- /dev/null
@@ -0,0 +1,556 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   width="885.40912"
+   height="138.02615"
+   sodipodi:docname="yourule_banner.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   sodipodi:docbase="/tmp"
+   version="1.0"
+   inkscape:export-filename="/tmp/yourule_banner.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <metadata
+     id="metadata191">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs189">
+    <linearGradient
+       id="linearGradient3312">
+      <stop
+         style="stop-color:#032466;stop-opacity:1;"
+         offset="0"
+         id="stop3314" />
+      <stop
+         id="stop4311"
+         offset="0.51612902"
+         style="stop-color:#829ac8;stop-opacity:1;" />
+      <stop
+         id="stop4309"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3312"
+       id="linearGradient3326"
+       x1="-1"
+       y1="85.749016"
+       x2="884.20636"
+       y2="85.749016"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0001854,0,0,0.7932477,1.0195184,0.9928715)" />
+  </defs>
+  <sodipodi:namedview
+     inkscape:cy="59.142887"
+     inkscape:cx="324.2777"
+     inkscape:zoom="0.61490055"
+     inkscape:window-height="587"
+     inkscape:window-width="860"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-x="56"
+     inkscape:window-y="54"
+     inkscape:current-layer="svg2">
+    <sodipodi:guide
+       orientation="vertical"
+       position="13.823373"
+       id="guide4313" />
+    <sodipodi:guide
+       orientation="vertical"
+       position="-4.606614"
+       id="guide4315" />
+  </sodipodi:namedview>
+  <rect
+     height="136.24471"
+     width="883.62769"
+     y="0.8907271"
+     x="0.8907271"
+     id="rect4"
+     style="fill:url(#linearGradient3326);fill-opacity:1;stroke:#000000;stroke-width:1.78145421;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+     rx="10"
+     ry="10"
+     inkscape:export-filename="/tmp/yourule_banner.png"
+     inkscape:export-xdpi="90.12661"
+     inkscape:export-ydpi="90.12661" />
+  <g
+     id="g4349"
+     style="stroke:#727272;stroke-opacity:1"
+     transform="matrix(1.0001854,0,0,0.7932477,1.9332533e-2,0.1996237)"
+     inkscape:export-filename="/tmp/yourule_banner.png"
+     inkscape:export-xdpi="90.12661"
+     inkscape:export-ydpi="90.12661">
+    <g
+       id="g4319"
+       style="stroke:#727272;stroke-opacity:1">
+      <line
+         y2="53.914421"
+         x2="15.607819"
+         y1="0.88384312"
+         x1="15.607819"
+         id="line8"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="30.331795"
+         y1="0.88384312"
+         x1="30.331795"
+         id="line10"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="45.055771"
+         y1="0.88384312"
+         x1="45.055771"
+         id="line14"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="107.45097"
+         x2="60.9314"
+         y1="1.3898103"
+         x1="60.9314"
+         id="line16"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="74.503723"
+         y1="0.88384312"
+         x1="74.503723"
+         id="line20"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="89.227707"
+         y1="0.88384312"
+         x1="89.227707"
+         id="line22"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="103.95169"
+         y1="0.88384312"
+         x1="103.95169"
+         id="line26"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="118.67566"
+         y1="0.88384312"
+         x1="118.67566"
+         id="line28"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="133.39964"
+         y1="0.88384312"
+         x1="133.39964"
+         id="line32"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="148.12361"
+         y1="0.88384312"
+         x1="148.12361"
+         id="line34"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="162.84758"
+         y1="0.88384312"
+         x1="162.84758"
+         id="line38"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="177.57156"
+         y1="0.88384312"
+         x1="177.57156"
+         id="line40"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="192.29555"
+         y1="0.88384312"
+         x1="192.29555"
+         id="line44"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="207.01952"
+         y1="0.88384312"
+         x1="207.01952"
+         id="line46"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="221.7435"
+         y1="0.88384312"
+         x1="221.7435"
+         id="line50"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="236.46745"
+         y1="0.88384312"
+         x1="236.46745"
+         id="line52"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="251.19145"
+         y1="0.88384312"
+         x1="251.19145"
+         id="line56"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="265.91541"
+         y1="0.88384312"
+         x1="265.91541"
+         id="line58"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="280.6394"
+         y1="0.88384312"
+         x1="280.6394"
+         id="line62"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="295.36337"
+         y1="0.88384312"
+         x1="295.36337"
+         id="line64"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="310.08737"
+         y1="0.88384312"
+         x1="310.08737"
+         id="line68"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="324.81134"
+         y1="0.88384312"
+         x1="324.81134"
+         id="line70"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="339.53531"
+         y1="0.88384312"
+         x1="339.53531"
+         id="line74"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="354.25928"
+         y1="0.88384312"
+         x1="354.25928"
+         id="line76"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="368.98328"
+         y1="0.88384312"
+         x1="368.98328"
+         id="line80"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="383.70724"
+         y1="0.88384312"
+         x1="383.70724"
+         id="line82"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="53.914421"
+         x2="398.43121"
+         y1="0.88384312"
+         x1="398.43121"
+         id="line86"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+      <line
+         y2="106.945"
+         x2="413.15518"
+         y1="0.88384312"
+         x1="413.15518"
+         id="line88"
+         style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+    </g>
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line92"
+       x1="427.87918"
+       y1="0.88384312"
+       x2="427.87918"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line94"
+       x1="442.60315"
+       y1="0.88384312"
+       x2="442.60315"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line98"
+       x1="457.32715"
+       y1="0.88384312"
+       x2="457.32715"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line100"
+       x1="472.05109"
+       y1="0.88384312"
+       x2="472.05109"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line104"
+       x1="486.77505"
+       y1="0.88384312"
+       x2="486.77505"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line106"
+       x1="501.49905"
+       y1="0.88384312"
+       x2="501.49905"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line110"
+       x1="516.22302"
+       y1="0.88384312"
+       x2="516.22302"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line112"
+       x1="530.94696"
+       y1="0.88384312"
+       x2="530.94696"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line116"
+       x1="545.67096"
+       y1="0.88384312"
+       x2="545.67096"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line118"
+       x1="560.39496"
+       y1="0.88384312"
+       x2="560.39496"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line122"
+       x1="575.11896"
+       y1="0.88384312"
+       x2="575.11896"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line124"
+       x1="589.8429"
+       y1="0.88384312"
+       x2="589.8429"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line128"
+       x1="604.56689"
+       y1="0.88384312"
+       x2="604.56689"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line130"
+       x1="619.29089"
+       y1="0.88384312"
+       x2="619.29089"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line134"
+       x1="634.01489"
+       y1="0.88384312"
+       x2="634.01489"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line136"
+       x1="648.73883"
+       y1="0.88384312"
+       x2="648.73883"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line140"
+       x1="663.46283"
+       y1="0.88384312"
+       x2="663.46283"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line142"
+       x1="678.18677"
+       y1="0.88384312"
+       x2="678.18677"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line146"
+       x1="692.91071"
+       y1="0.88384312"
+       x2="692.91071"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line148"
+       x1="707.6347"
+       y1="0.88384312"
+       x2="707.6347"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line152"
+       x1="722.3587"
+       y1="0.88384312"
+       x2="722.3587"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line154"
+       x1="737.0827"
+       y1="0.88384312"
+       x2="737.0827"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line158"
+       x1="751.80664"
+       y1="0.88384312"
+       x2="751.80664"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line160"
+       x1="766.53064"
+       y1="0.88384312"
+       x2="766.53064"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line164"
+       x1="781.25464"
+       y1="0.88384312"
+       x2="781.25464"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line166"
+       x1="795.97864"
+       y1="0.88384312"
+       x2="795.97864"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line170"
+       x1="810.70258"
+       y1="0.88384312"
+       x2="810.70258"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line172"
+       x1="825.42651"
+       y1="0.88384312"
+       x2="825.42651"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line176"
+       x1="840.15051"
+       y1="0.88384312"
+       x2="840.15051"
+       y2="53.914421" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line178"
+       x1="854.87451"
+       y1="0.88384312"
+       x2="854.87451"
+       y2="106.945" />
+    <line
+       style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+       id="line182"
+       x1="869.59845"
+       y1="0.88384312"
+       x2="869.59845"
+       y2="53.914421" />
+  </g>
+  <text
+     xml:space="preserve"
+     style="font-size:12.6378603px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+     x="13.549175"
+     y="98.016769"
+     id="text3332"
+     inkscape:export-filename="/tmp/yourule_banner.png"
+     inkscape:export-xdpi="90.12661"
+     inkscape:export-ydpi="90.12661"><tspan
+       sodipodi:role="line"
+       id="tspan3334"
+       x="13.549175"
+       y="98.016769"
+       style="font-size:63.18930054px;font-weight:bold;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans Mono">YouRule</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:13.47839546px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+     x="12.11779"
+     y="129.42696"
+     id="text3336"
+     inkscape:export-filename="/tmp/yourule_banner.png"
+     inkscape:export-xdpi="90.12661"
+     inkscape:export-ydpi="90.12661"><tspan
+       sodipodi:role="line"
+       id="tspan3338"
+       x="12.11779"
+       y="129.42696"
+       style="font-size:33.6959877px;font-weight:bold;fill:#ffffff;fill-opacity:1">Onscreen Ruler Generator</tspan></text>
+</svg>
diff --git a/static/style.css b/static/style.css
new file mode 100644 (file)
index 0000000..b589157
--- /dev/null
@@ -0,0 +1,137 @@
+@charset "UTF-8";
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  outline: 0;
+  font-weight: inherit;
+  font-style: inherit;
+  font-family: inherit;
+  vertical-align: baseline;
+}
+
+body {
+  font: Arial, Helvetica, sans-serif;
+}
+
+label {
+  font-weight: bold;
+}
+
+em {
+  font-style: italic;
+}
+
+#wrapper {
+  padding: 1em 0 0 0;
+  margin: 0 auto 0 auto;
+  width: 885px;
+}
+
+#header {
+  width: 885px;
+  height: 138px;
+  background: url(/static/images/yourule_banner.png);
+}
+
+#header h1, #header h2 {
+  display: none;
+}
+
+.mainbox {
+  margin-top: 1em;
+  background: url(/static/images/tl.png) no-repeat top left;
+}
+
+.mainbox_top {
+  background: url(/static/images/tr.png) no-repeat top right;
+}
+
+.mainbox_bottom {
+  background: url(/static/images/bl.png) no-repeat bottom left;
+}
+
+.mainbox_bottom div {
+  background: url(/static/images/br.png) no-repeat bottom right;
+}
+
+.mainbox_content {
+  background: url(/static/images/r.png) top right repeat-y;
+}
+
+
+.mainbox_top div, .mainbox_top, .mainbox_bottom div, .mainbox_bottom {
+  width: 100%;
+  height: 30px;
+  font-size: 1px;
+}
+
+.mainbox_content, .mainbox_bottom {
+  margin-top: -19px;
+}
+
+.mainbox_content {
+  padding: 0em 3em 2em 3em;
+  line-height: 1.5em;
+}
+
+.mainbox_content h2 {
+ border-bottom: 3px #1e3d7b solid;
+ margin: 19px 0 0.8em 0;
+ font-weight: bold;
+}
+
+.mainbox_content p {
+  margin-bottom: 0.5em;
+}
+
+#gallery {
+  border: 1px solid #1e3d7b;
+  width: 100%;
+  border-collapse: collapse;
+}
+
+#gallery th {
+  background: #1e3d7b;
+  color: white;
+}
+
+#gallery td {
+  text-align: center;
+}
+
+#menu {
+  text-align: right;
+  margin: 0.5em;
+}
+
+#rulerimg {
+  margin: 0.5em;
+}
+
+.errormsg {
+  background-color: #f7fb70;
+  color: #4c4c4c;
+  text-align: center;
+  border: 1px #fdff00 solid;
+  width: 20em;
+  margin: 1em;
+}
+
+strong {
+  font-weight: bold;
+}
+
+#footer {
+  margin-top: 3em;
+  font-size: 0.8em;
+  text-align: center;
+}
similarity index 97%
rename from ruler.py
rename to svgruler.py
index 39bcd3d0e45302bb472b6e3389994e429b4785f1..7c66050fefac06132b4ab41ea4a371074b27da95 100644 (file)
--- a/ruler.py
@@ -2,7 +2,7 @@
 from __future__ import division
 import SVGdraw
 
-class Ruler:
+class SVGRuler:
     def __init__(self, scale=None, units=None,
                  ruler_height=None, ruler_length=None):
 
@@ -49,14 +49,14 @@ class Ruler:
                 self.__drawline(0.3)
             
             self.__drawline(0.6)
-            self.svg.addElement(SVGdraw.text((self.point - font_height * 1.4),
+            self.svg.addElement(SVGdraw.text((self.point - font_height * 1.15),
                            (self.ruler_height * 0.6 - 5),
                             str(i + 1), font_height))
     
 
         self.drawing.setSVG(self.svg)
 
-    def output(self):
+    def getxml(self):
         import cStringIO
         xml = cStringIO.StringIO()
         xml.write("<?xml version='1.0' encoding='UTF-8'?>\n")
index 18c57c883c20a7dcdd6ea9dfa20f0a11a992b590..b365ce05579308c8e2abfd557d10de028731b7ea 100644 (file)
@@ -1,14 +1,14 @@
-<p>Units:
+<p><label for="units">Units:</label>
 <select id="unitselector" name="units">
 <option values="centimeters"#if $getVar('units', '') == 'centimeters'# selected="selected"'#end if#>centimeters</option>
 <option value="inches"#if $getVar('units', '') == 'inches'# selected="selected"'#end if#>inches</option>
 </select>
 </p>
 
-<p><label for="pixel_width">Your screen width (in pixels):</label>
+<p><label for="pixel_width">Screen width (in pixels):</label>
 <input type="text" name="pixel_width" value="$getVar('pixel_width', None)" /></p>
 
-<p><label for="unit_width">Your screen width (in <span class="unittext">units</span>):</label>
+<p><label for="unit_width"><em>Horizontal</em> screen width (in <span class="unittext">units</span>):</label>
 <input type="text" name="unit_width" value="$getVar('unit_width', None)" /></p>
 
 <script>
index b615ef54ed941f82a5bbbd6b061f13442a2ca453..0a94f91760fd27988c88590b35f5f7246f15a64c 100644 (file)
@@ -4,7 +4,7 @@
 
 <h2>Gallery of Existing Rulers</h2>
 
-<table>
+<table id="gallery">
 <tr>
 <th>Model</th>
 <th>Pixel Width</th>
@@ -18,8 +18,7 @@
   <td>$ruler.pixel_width</td>
   <td>$ruler.cm_width()/$ruler.in_width</td>
   <td>
-    <a href="/show/ruler_${ruler.pixel_width}px_${ruler.cm_width}centimeters.png?fromgallery=true">cm</a>
-    <a href="/show/ruler_${ruler.pixel_width}px_${ruler.in_width}inches.png?fromgallery=true">in</a>
+    <a href="/show/ruler_${ruler.pixel_width}px_${ruler.cm_width}centimeters.png?fromgallery=true">cm</a>/<a href="/show/ruler_${ruler.pixel_width}px_${ruler.in_width}inches.png?fromgallery=true">in</a>
   </td>
   <td><form method="GET" action="delete/$ruler.id" style="display:inline;">
       <input type="submit" value="delete" /></form></td>
 <p>If your ruler is not on the list you should add it with the box
 form.</p>
 
-
+#if $getVar('errormsg', False)
+<div class="errormsg">
+<strong>Error</strong><br />
+$getVar('errormsg', False)
+</div>
+#end if
 <form method="POST" action="/gallery">
 
 #include 'templates/_form_elements.tmpl'
index d8cdc8158f0119c03c8bcd9c2dde93b0823c0002..7d2832c2b18182451cb48aacf7751697c1361a71 100644 (file)
@@ -2,10 +2,21 @@
 
 #block body
 
-<h1>Screen Ruler Generator</h1>
+<h2>Ruler Gallery </h2>
 
-<h2>Create a new screen ruler</h2>
+<p>To view a list of rulers others have created or to save your ruler so
+that others with your computer can find it, visit the <a
+href="/gallery">ruler gallery</a>.</p>
+
+<h2>Create Custom Ruler</h2>
 
+#if $getVar('errormsg', False)
+<div class="errormsg">
+<strong>Error</strong><br />
+$getVar('errormsg', False)
+</div>
+
+#end if
 <form method="POST" action="/">
 
 #include 'templates/_form_elements.tmpl'
@@ -13,8 +24,5 @@
 <input type="Submit" name="submit" value="Generate" />
 <form>
 
-<p>To view a list of rulers others have created or to save your ruler so
-that others with your computer can find it, visit the <a
-href="/gallery">ruler gallery</a>.</p>
 
 #end block body
index 397314ffdf4833bc81c00302f29eded3a25c28a0..ac20fd61088d15f88b30cedc92bcc72411845db6 100644 (file)
@@ -1,17 +1,19 @@
-#extends site
-
-#block body
-
-<h2>Your Ruler</h2>
-
-<img src="/$ruler_url" alt="$ruler_url" />
-
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="/static/style.css" />
+</head>
+<p id="menu">
+<a href="/show/$other_unit_url">show in $other_unit</a>
+/
 #if $fromgallery
-<p><a href="/gallery">Back to gallery</a>.</p>
+<a href="/gallery">back to gallery</a>
 #else
-<p><a href="/gallery/$ruler_url">Save your ruler to the gallery</a> for others to use in
-the future.</p>
+<a href="/gallery/$ruler_url">save for others</a>
 #end if
+</p>
+
+<div id="rulerimg">
+<img src="/$ruler_url" alt="$ruler_url" />
+</div>
 
-#end block body
 
index 75461cf759ab53379da29fd4a38e62cb2ff551eb..53cfed33168712694ed0453501d3946488ea25dd 100644 (file)
@@ -1,10 +1,34 @@
 <html>
 <head>
+  <link rel="stylesheet" type="text/css" href="/static/style.css" />
   <script src="/static/prototype.js" type="text/javascript"></script>
 </head>
 <body>
+<div id="wrapper">
+<div id="header">
+<h1>YouRule</h1>
+<h2>Onscreen Ruler Generator</h2>
+</div>
+
+<div class="mainbox">
+  <div class="mainbox_top"><div></div></div>
+  <div class="mainbox_content">
+
 #filter Filter
 $body
 #end filter
+  </div>
+  <div class="mainbox_bottom"><div></div></div>
+</div>
+
+<div id="footer">
+<p>copyright 2007 :: <a href="http://mako.cc/">benjamin mako hill</a><br />
+<a href="http://mako.cc/projects/yourule">source freely available</a> :: <a
+href="http://www.affero.org/oagpl.html">affero general public
+license</a></p>
+</div>
+
+</div>
+
 </body>
 </html>
diff --git a/yourule.py b/yourule.py
new file mode 100755 (executable)
index 0000000..9010217
--- /dev/null
@@ -0,0 +1,220 @@
+#!/usr/bin/env python
+
+from __future__ import division
+import web
+import sys, os, re
+from storm.locals import *
+from svgruler import SVGRuler
+
+# the url map for the application
+urls = ( '/', 'index',
+         '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
+         '/show/(.*(svg|png|jpg))', 'show_ruler',
+         '/gallery(.*)', 'gallery',
+         '/delete/(\d+)', 'delete',
+         '/undelete/(\d+)', 'undelete')
+
+database = create_database("sqlite:yourule.db")
+store = Store(database)
+
+class Ruler(object):
+    __storm_table__ = "gallery"
+    id = Int(primary=True)
+    pixel_width = Float()
+    unit_width = Float()
+    model = Unicode()
+    units = Unicode()
+    show = Int()
+    cm_in_ratio = 0.3937
+
+    def __init__(self, **kw):
+        self.pixel_width = float(kw['pixel_width'])
+        self.unit_width = float(kw['unit_width'])
+        self.units = unicode(kw['units'])
+        if kw.has_key('model'):
+            self.model = unicode(kw['model'])
+        else:
+            self.model = u''
+
+    def cm_width(self):
+        if self.units == 'centimeters':
+            return self.unit_width
+        elif self.units == 'inches':
+            return(round(self.unit_width / self.cm_in_ratio, 2))
+
+    def in_width(self):
+        if self.units == 'inches':
+            return self.unit_width
+        elif self.units == 'centimeters':
+            return(round(self.unit_width * self.cm_in_ratio, 2))
+
+    def url(self):
+        return('ruler_%spx_%s%s.png' % (self.pixel_width,
+                                        self.unit_width, self.units))
+
+
+class index:
+    def GET(self):
+        web.header("Content-Type","text/html; charset=utf-8")
+        web.render('index.tmpl')
+
+    def POST(self):
+        input = web.input()
+
+        errormsg = validate_input(input)
+
+        if errormsg:
+            pixel_width = input['pixel_width']
+            unit_width = input['unit_width']
+            units = input['units']
+            web.render('index.tmpl')
+        else:
+            ruler = Ruler(pixel_width = input['pixel_width'], 
+                          unit_width = input['unit_width'], 
+                          units = input['units'])
+            
+            web.redirect('/show/%s' % ruler.url())
+
+class show_ruler:
+    def GET(self, ruler_url, ext):
+        web.debug('test test')
+        if web.input().has_key('fromgallery'):
+            fromgallery = True
+        else:
+            fromgallery = False
+
+        other_unit, other_unit_url = get_other_unit(ruler_url)
+
+        web.header("Content-Type","text/html; charset=utf-8")
+        web.render('show_ruler.tmpl')
+
+
+class ruler_img:
+    def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
+
+        # TODO check to see if it's a format that we support
+
+        # set ruler height to be 200 px always
+        pixel_width = float(pixel_width)
+        unit_width = float(unit_width)
+
+        ruler_height = 200
+
+        scale = pixel_width / unit_width
+        ruler_length = int(unit_width)
+
+        ruler = SVGRuler(scale, units, ruler_height, ruler_length)
+
+        # print the header
+        if ext == 'svg': ext = 'svg+xml'
+        web.header("Content-Type", "image/%s" % ext)
+
+        if ext == 'svg+xml':
+            sys.stdout.write(ruler.getxml())
+        else:
+            pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
+                                  (pixel_width, ruler_height, ext))
+
+            pin.write(ruler.getxml())
+            pin.close()
+            sys.stdout.write(pout.read())
+
+class gallery:
+    def GET(self, ruler_url):
+
+        if ruler_url:
+            pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
+
+        rulers = store.find(Ruler, Ruler.show == 1)
+        rulers.order_by(Ruler.model)
+        web.render('gallery.tmpl')
+
+    def POST(self, ruler_url):
+        input = web.input()
+
+        errormsg = valid_input(input)
+        if not input.model:
+            errormsg = 'Please fill out all fields.'
+
+        if errormsg:
+            pixel_width = input['pixel_width']
+            unit_width = input['unit_width']
+            units = input['units']
+            model = input['model']
+        else:
+            new_ruler = Ruler(pixel_width = input['pixel_width'],
+                              unit_width = input['unit_width'],
+                              units = input['units'],
+                              model = input['model'])
+
+            store.add(new_ruler)
+            store.commit()
+
+        rulers = store.find(Ruler, Ruler.show == 1)
+        rulers.order_by(Ruler.model)
+        web.render('gallery.tmpl')
+
+class delete:
+    def GET(self, id):
+        ruler = store.get(Ruler, int(id))
+        ruler.show = 0
+        store.commit()
+        web.redirect('/gallery')
+
+
+class undelete:
+    def GET(self, id):
+        ruler = store.get(Ruler, int(id))
+        ruler.show = 1
+        store.commit()
+        web.redirect('/gallery')
+
+def get_other_unit(url):
+    pixel_width, unit_width, units = process_ruler_url(url)[0:3]
+
+    ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width, units=units)
+    pixel_width, unit_width, units = process_ruler_url(url)[0:3]
+
+    if units == 'centimeters':
+        units = 'inches'
+        unit_width = ruler.in_width()
+    elif units == 'inches':
+        units = 'centimeters'
+        unit_width = ruler.cm_width()
+
+    new_ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width,
+                      units=units)
+
+    web.debug(units)
+    return(units, new_ruler.url())
+
+
+def process_ruler_url(url):
+    url = re.sub(r'^/?(ruler.*)$', r'\1', url)
+    return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
+           url).groups())
+
+def validate_input(input):
+    errormsg = False
+
+    if not input.pixel_width \
+        or not input.unit_width:
+        errormsg = 'Please fill out all fields.'
+    elif not re.match('^[\d\.]+$', input.pixel_width) \
+        or not re.match('^[\d\.]+$', input.unit_width):
+        errormsg = "Widths must be numbers."
+    elif input['pixel_width'] < 0 \
+        or input['unit_width'] < 0:
+        errormsg = 'Widths must be greater than postive.'
+
+    return(errormsg)
+
+# render the site template here so that i can use it later
+web.render('site.tmpl', None, True, 'site')
+
+web.webapi.internalerror = web.debugerror
+if __name__ == "__main__":
+    web.run(urls, globals(), web.reloader)
+
+application = web.wsgifunc(web.webpyfunc(urls, globals()))
+

Benjamin Mako Hill || Want to submit a patch?