#!/usr/bin/env python
'''
Copyright (C) 2009 Sascha Poczihoski, sascha@junktech.de

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

TODO
	- fix bug: special chars in suffix
'''

import sys, math
sys.path.append('/usr/share/inkscape/extensions') # or another path, as necessary
import inkex
from simplestyle import *


class ScaleGen(inkex.Effect):
    """
    Example Inkscape effect extension.
    Creates a new layer with a "Hello World!" text centered in the middle of the document.
    """
    def __init__(self):
        """
        Constructor.
        Defines the "--what" option of a script.
        """
        # Call the base class constructor.
        inkex.Effect.__init__(self)

        # Define string option "--what" with "-w" shortcut and default value "World".
        self.OptionParser.add_option('-f', '--scalefrom', action = 'store',
          type = 'int', dest = 'scalefrom', default = '0',
          help = 'Measure from...')
        self.OptionParser.add_option('-t', '--scaleto', action = 'store',
          type = 'int', dest = 'scaleto', default = '20',
          help = 'Measure to...')
        self.OptionParser.add_option('-c', '--reverse', action = 'store',
          type = 'string', dest = 'reverse', default = 'false',
          help = 'Reverse order:')             
        self.OptionParser.add_option('', '--rotate', action = 'store',
          type = 'string', dest = 'rotate', default = '0',
          help = 'Rotate:')                   
        self.OptionParser.add_option('-b', '--scaleres', action = 'store',
          type = 'int', dest = 'scaleres', default = '100',
          help = 'Measure resolution:')                   
        self.OptionParser.add_option('-g', '--scaleheight', action = 'store',
          type = 'int', dest = 'scaleheight', default = '100',
          help = 'Height of scale:')
        self.OptionParser.add_option('-s', '--fontsize', action = 'store',
          type = 'int', dest = 'fontsize', default = '16',
          help = 'Font Size:')
        self.OptionParser.add_option('-i', '--suffix', action = 'store',
          type = 'string', dest = 'suffix', default = '',
          help = 'Suffix:')

	# label offset
        self.OptionParser.add_option('-x', '--labeloffseth', action = 'store',
          type = 'int', dest = 'labeloffseth', default = '45',
          help = 'Label offset h:')   
        self.OptionParser.add_option('-y', '--labeloffsetv', action = 'store',
          type = 'int', dest = 'labeloffsetv', default = '45',
          help = 'Label offset v:') 
          
        # marker div
        self.OptionParser.add_option('-m', '--mark0', action = 'store',
          type = 'int', dest = 'mark0', default = '10',
          help = 'Div of labeled marker:')
        self.OptionParser.add_option('-n', '--mark1', action = 'store',
          type = 'int', dest = 'mark1', default = '5',
          help = 'Div of bold marker:')
        self.OptionParser.add_option('-o', '--mark2', action = 'store',
          type = 'int', dest = 'mark2', default = '1',
          help = 'Div of standard marker:')
          
        # marker strength        
        self.OptionParser.add_option('-p', '--mark0str', action = 'store',
          type = 'float', dest = 'mark0str', default = '10.0',
          help = 'Strength of labeled marker:')
        self.OptionParser.add_option('-q', '--mark1str', action = 'store',
          type = 'float', dest = 'mark1str', default = '5.0',
          help = 'Strength of bold marker:')
        self.OptionParser.add_option('-r', '--mark2str', action = 'store',
          type = 'float', dest = 'mark2str', default = '1.0',
          help = 'Strength of standard marker:')
          
        # marker width
        self.OptionParser.add_option('-w', '--mark1wid', action = 'store',
          type = 'int', dest = 'mark1wid', default = '75',
          help = 'Width of bold marker (\%):')
        self.OptionParser.add_option('-v', '--mark2wid', action = 'store',
          type = 'int', dest = 'mark2wid', default = '50',
          help = 'Width of standard marker (\%):')       
                             
        self.OptionParser.add_option('-u', '--unit', action = 'store',
          type = 'string', dest = 'unit', default = 'mm',
          help = 'Unit:')                                

    def addLabel(self, i, x, y, grp, fontsize):
    	res = self.options.scaleres
    	pos = i*res + fontsize/2
    	text = inkex.etree.SubElement(grp, inkex.addNS('text','svg'))
    	text.text = str(i)+self.options.suffix.encode("utf8")
    	#rotate = self.options.rotate
    	fs = str(fontsize)
        style = {'text-align' : 'center', 'text-anchor': 'middle', 'font-size': fs}
        text.set('style', formatStyle(style))
#        text.set('x', str(inkex.unittouu(str(x)+self.options.unit)+self.options.labeloffseth))
#        text.set('y', str(inkex.unittouu(str(y)+self.options.unit)+self.options.labeloffsetv))
        text.set('x', str(float(x)+int(self.options.labeloffseth)))
        text.set('y', str(float(y)+int(self.options.labeloffsetv)))        
        grp.append(text)
        
    def addLine(self, i, scalefrom, scaleto, grp, grpLabel, type=2):
    	reverse = self.options.reverse
    	rotate = self.options.rotate
    	unit = self.options.unit    	
    	fontsize = self.options.fontsize
    	res = self.options.scaleres
    	label = False
    	if reverse=='true':
    		# Count absolut i for labeling
    		counter = 0
 		for n in range(scalefrom, i):
 			counter += 1
 		n = scaleto-counter-1
 	else:
 		n = i
		
    	if type==0:
	    	line_style   = { 'stroke': 'red',
        	             'stroke-width': str(self.options.mark0str) }
        	x1 = 0
        	y1 = i*res
        	x2 = self.options.scaleheight
        	y2 = i*res
        	
        	label = True
        	
    	if type==1:
	    	line_style   = { 'stroke': 'black',
        	             'stroke-width': str(self.options.mark1str) }
        	x1 = 0
        	y1 = i*res
        	x2 = self.options.scaleheight*0.01*self.options.mark1wid
        	y2 = i*res
        	
    	if type==2:
	    	line_style   = { 'stroke': 'black',
        	             'stroke-width': str(self.options.mark2str) }
        	x1 = 0
        	y1 = i*res
        	x2 = self.options.scaleheight*0.01*self.options.mark2wid
        	y2 = i*res    	      

       	x1 = str(self.unittouu(str(x1)+unit) )
       	y1 = str(self.unittouu(str(y1)+unit) )
       	x2 = str(self.unittouu(str(x2)+unit) )
       	y2 = str(self.unittouu(str(y2)+unit) )
       	if rotate=='90':
       		tx = x1
	       	x1 = y1
       		y1 = tx
       			
       		tx = x2
       		x2 = y2
       		y2 = tx
       	
    	if label==True:
		self.addLabel(n , x2, y2, grpLabel, fontsize)
    	line_attribs = {'style' : formatStyle(line_style),
                    inkex.addNS('label','inkscape') : 'name',
                    'd' : 'M '+x1+','+y1+' L '+x2+','+y2}

    	line = inkex.etree.SubElement(grp, inkex.addNS('path','svg'), line_attribs )
   	

    def effect(self):
    	
        scalefrom = self.options.scalefrom
        scaleto = self.options.scaleto
        scaleheight = self.options.scaleheight
        mark0 = self.options.mark0
        mark1 = self.options.mark1
        mark2 = self.options.mark2

        # Get access to main SVG document element and get its dimensions.
        svg = self.document.getroot()

        # Again, there are two ways to get the attributes:
        width  = svg.get('width')
        height = svg.get('height')
        
        # Create new group
        centre = self.view_center   #Put in in the centre of the current view
	grp_transform = 'translate' + str( centre )

        grp_name = 'Scale Labels'
        grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
                           'transform':grp_transform }
	grpLabel = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)
		
	grp_name = 'Scale Mark labeled'
        grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
                           'transform':grp_transform }
	grpMark0 = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)
	grp_name = 'Scale Mark medium'
        grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
                           'transform':grp_transform }
	grpMark1 = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)	
	grp_name = 'Scale Mark default'
        grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
                           'transform':grp_transform }
	grpMark2 = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)	

	# to allow positive to negative counts
        if scalefrom < scaleto:
        	scaleto += 1
        else:
        	temp = scaleto
        	scaleto = scalefrom+1
        	scalefrom = temp
 	
	skip = 0
        for i in range(scalefrom, scaleto):
        	if (i % mark0)==0:
        		div = 0		# This a the labeled marker
        		grpMark = grpMark0
        	elif (i % mark1)==0:
        		div = 1 	# the medium marker
        		grpMark = grpMark1
        	elif (i % mark2)==0:
        		div = 2 	# the default marker
        		grpMark = grpMark2
        	else:
        		skip=1	# Don't print a marker this time	        		
        	if skip==0:
        		self.addLine(i, scalefrom, scaleto, grpMark, grpLabel, div) # addLabel is called from inside
        	skip = 0


# Create effect instance and apply it.
effect = ScaleGen()
effect.affect()

