diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2015-10-22 20:04:30 +0000 |
|---|---|---|
| committer | jabiertxof <jabier.arraiza@marker.es> | 2015-10-22 20:04:30 +0000 |
| commit | d436959141dafd9de4c82f2ff0136bcfcebbe473 (patch) | |
| tree | 12349d76e5c440e622df9ed0ddf21c7c147673ac /share | |
| parent | working in spray tool (diff) | |
| parent | Translations. Icelandic translation update. (diff) | |
| download | inkscape-d436959141dafd9de4c82f2ff0136bcfcebbe473.tar.gz inkscape-d436959141dafd9de4c82f2ff0136bcfcebbe473.zip | |
update to trunk
(bzr r14422.1.4)
Diffstat (limited to 'share')
| -rw-r--r-- | share/extensions/restack.inx | 62 | ||||
| -rwxr-xr-x | share/extensions/restack.py | 252 |
2 files changed, 199 insertions, 115 deletions
diff --git a/share/extensions/restack.inx b/share/extensions/restack.inx index 67f0f777a..4f5f577cb 100644 --- a/share/extensions/restack.inx +++ b/share/extensions/restack.inx @@ -4,25 +4,49 @@ <id>org.inkscape.filter.restack</id> <dependency type="executable" location="extensions">restack.py</dependency> <dependency type="executable" location="extensions">inkex.py</dependency> - <param name="direction" type="enum" _gui-text="Restack Direction:"> - <_item value="lr">Left to Right (0)</_item> - <_item value="bt">Bottom to Top (90)</_item> - <_item value="rl">Right to Left (180)</_item> - <_item value="tb">Top to Bottom (270)</_item> - <_item value="ro">Radial Outward</_item> - <_item value="ri">Radial Inward</_item> - <_item value="aa">Arbitrary Angle</_item> - </param> - <param name="angle" type="float" min="0.0" max="360.0" _gui-text="Angle:">0.00</param> - <param name="xanchor" type="enum" _gui-text="Horizontal Point:"> - <_item value="l">Left</_item> - <_item value="m">Middle</_item> - <_item value="r">Right</_item> - </param> - <param name="yanchor" type="enum" _gui-text="Vertical Point:"> - <_item value="t">Top</_item> - <_item value="m">Middle</_item> - <_item value="b">Bottom</_item> + <param name="tab" type="notebook"> + <page name="positional" _gui-text="Based on Position"> + <_param name="desc_dir" type="description" appearance="header">Restack Direction</_param> + <param name="nb_direction" type="notebook"> + <page name="presets" _gui-text="Presets"> + <param name="direction" type="enum" _gui-text=""> + <_item value="lr">Left to Right (0)</_item> + <_item value="bt">Bottom to Top (90)</_item> + <_item value="rl">Right to Left (180)</_item> + <_item value="tb">Top to Bottom (270)</_item> + <_item value="ro">Radial Outward</_item> + <_item value="ri">Radial Inward</_item> + </param> + </page> + <page name="custom" _gui-text="Custom"> + <param name="angle" type="float" min="0.0" max="360.0" _gui-text="Angle:">0.00</param> + </page> + </param> + <_param name="desc_ref" type="description" appearance="header">Object Reference Point</_param> + <param name="xanchor" type="enum" _gui-text="Horizontal:"> + <_item value="l">Left</_item> + <_item value="m">Middle</_item> + <_item value="r">Right</_item> + </param> + <param name="yanchor" type="enum" _gui-text="Vertical:"> + <_item value="t">Top</_item> + <_item value="m">Middle</_item> + <_item value="b">Bottom</_item> + </param> + </page> + <page name="z_order" _gui-text="Based on Z-Order"> + <_param name="desc_zsort" type="description" appearance="header">Restack Mode</_param> + <param name="zsort" type="enum" _gui-text=""> + <_item value="rev">Reverse Z-Order</_item> + <_item value="rand">Shuffle Z-Order</_item> + </param> + </page> + <page name="help" _gui-text="Help"> + <_param name="desc_help" type="description">This extension changes the z-order of objects based on their position on the canvas or their current z-order. + +Selection: +The extension restacks either objects inside a single selected group, or a selection of multiple objects on the current drawing level (layer or group).</_param> + </page> </param> <effect> <object-type>path</object-type> diff --git a/share/extensions/restack.py b/share/extensions/restack.py index dc877cd9e..67d738a13 100755 --- a/share/extensions/restack.py +++ b/share/extensions/restack.py @@ -21,7 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import inkex, os, csv, math +import inkex, os, csv, math, random +from pathmodifier import zSort + +inkex.localize() try: from subprocess import Popen, PIPE @@ -48,103 +51,160 @@ class Restack(inkex.Effect): action="store", type="string", dest="yanchor", default="m", help="vertical point to compare") + self.OptionParser.add_option("--zsort", + action="store", type="string", + dest="zsort", default="rev", + help="Restack mode based on Z-Order") + self.OptionParser.add_option("--tab", + action="store", type="string", + dest="tab", + help="The selected UI-tab when OK was pressed") + self.OptionParser.add_option("--nb_direction", + action="store", type="string", + dest="nb_direction", + help="The selected UI-tab when OK was pressed") + def effect(self): - if len( self.selected ) > 0: - objlist = [] - svg = self.document.getroot() + if self.options.tab == '"help"': + pass + elif len(self.selected) > 0: + if self.options.tab == '"positional"': + self.restack_positional() + elif self.options.tab == '"z_order"': + self.restack_z_order() + else: + inkex.errormsg(_("There is no selection to restack.")) + + def restack_positional(self): + objects = {} + objlist = [] + file = self.args[ -1 ] + + if self.options.nb_direction == '"custom"': + self.options.direction = "aa" + + # process selection to get list of objects to be arranged + firstobject = self.selected[self.options.ids[0]] + if len(self.selected) == 1 and firstobject.tag == inkex.addNS('g', 'svg'): + parentnode = firstobject + for child in parentnode.iterchildren(): + objects[child.get('id')] = child + else: parentnode = self.current_layer - file = self.args[ -1 ] - - #get all bounding boxes in file by calling inkscape again with the --query-all command line option - #it returns a comma separated list structured id,x,y,w,h - if bsubprocess: - p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) - err = p.stderr - f = p.communicate()[0] - try: - reader=csv.CSVParser().parse_string(f) #there was a module cvs.py in earlier inkscape that behaved differently - except: - reader=csv.reader(f.split( os.linesep )) - err.close() - else: - _,f,err = os.popen3('inkscape --query-all "%s"' % ( file ) ) - reader=csv.reader( f ) - err.close() - - #build a dictionary with id as the key - dimen = dict() - for line in reader: - if len(line) > 0: - dimen[line[0]] = map( float, line[1:]) - - if not bsubprocess: #close file if opened using os.popen3 - f.close - - #find the center of all selected objects **Not the average! - x,y,w,h = dimen[self.selected.keys()[0]] - minx = x - miny = y - maxx = x + w - maxy = y + h - - for id, node in self.selected.iteritems(): - # get the bounding box - x,y,w,h = dimen[id] - if x < minx: - minx = x - if (x + w) > maxx: - maxx = x + w - if y < miny: - miny = y - if (y + h) > maxy: - maxy = y + h - - midx = (minx + maxx) / 2 - midy = (miny + maxy) / 2 - - #calculate distances for each selected object - for id, node in self.selected.iteritems(): - # get the bounding box - x,y,w,h = dimen[id] - - # calc the comparison coords - if self.options.xanchor == "l": - cx = x - elif self.options.xanchor == "r": - cx = x + w - else: # middle - cx = x + w / 2 - - if self.options.yanchor == "t": - cy = y - elif self.options.yanchor == "b": - cy = y + h - else: # middle - cy = y + h / 2 - - #direction chosen - if self.options.direction == "tb" or (self.options.direction == "aa" and self.options.angle == 270): - objlist.append([cy,id]) - elif self.options.direction == "bt" or (self.options.direction == "aa" and self.options.angle == 90): - objlist.append([-cy,id]) - elif self.options.direction == "lr" or (self.options.direction == "aa" and (self.options.angle == 0 or self.options.angle == 360)): - objlist.append([cx,id]) - elif self.options.direction == "rl" or (self.options.direction == "aa" and self.options.angle == 180): - objlist.append([-cx,id]) - elif self.options.direction == "aa": - distance = math.hypot(cx,cy)*(math.cos(math.radians(-self.options.angle)-math.atan2(cy, cx))) - objlist.append([distance,id]) - elif self.options.direction == "ro": - distance = math.hypot(midx - cx, midy - cy) - objlist.append([distance,id]) - elif self.options.direction == "ri": - distance = -math.hypot(midx - cx, midy - cy) - objlist.append([distance,id]) - - objlist.sort() - #move them to the top of the object stack in this order. - for item in objlist: - parentnode.append( self.selected[item[1]]) + objects = self.selected + + #get all bounding boxes in file by calling inkscape again with the --query-all command line option + #it returns a comma separated list structured id,x,y,w,h + if bsubprocess: + p = Popen('inkscape --query-all "%s"' % (file), shell=True, stdout=PIPE, stderr=PIPE) + err = p.stderr + f = p.communicate()[0] + try: + reader=csv.CSVParser().parse_string(f) #there was a module cvs.py in earlier inkscape that behaved differently + except: + reader=csv.reader(f.split( os.linesep )) + err.close() + else: + _,f,err = os.popen3('inkscape --query-all "%s"' % ( file ) ) + reader=csv.reader( f ) + err.close() + + #build a dictionary with id as the key + dimen = dict() + for line in reader: + if len(line) > 0: + dimen[line[0]] = map( float, line[1:]) + + if not bsubprocess: #close file if opened using os.popen3 + f.close + + #find the center of all selected objects **Not the average! + x,y,w,h = dimen[objects.keys()[0]] + minx = x + miny = y + maxx = x + w + maxy = y + h + + for id, node in objects.iteritems(): + # get the bounding box + x,y,w,h = dimen[id] + if x < minx: + minx = x + if (x + w) > maxx: + maxx = x + w + if y < miny: + miny = y + if (y + h) > maxy: + maxy = y + h + + midx = (minx + maxx) / 2 + midy = (miny + maxy) / 2 + + #calculate distances for each selected object + for id, node in objects.iteritems(): + # get the bounding box + x,y,w,h = dimen[id] + + # calc the comparison coords + if self.options.xanchor == "l": + cx = x + elif self.options.xanchor == "r": + cx = x + w + else: # middle + cx = x + w / 2 + + if self.options.yanchor == "t": + cy = y + elif self.options.yanchor == "b": + cy = y + h + else: # middle + cy = y + h / 2 + + #direction chosen + if self.options.direction == "tb" or (self.options.direction == "aa" and self.options.angle == 270): + objlist.append([cy,id]) + elif self.options.direction == "bt" or (self.options.direction == "aa" and self.options.angle == 90): + objlist.append([-cy,id]) + elif self.options.direction == "lr" or (self.options.direction == "aa" and (self.options.angle == 0 or self.options.angle == 360)): + objlist.append([cx,id]) + elif self.options.direction == "rl" or (self.options.direction == "aa" and self.options.angle == 180): + objlist.append([-cx,id]) + elif self.options.direction == "aa": + distance = math.hypot(cx,cy)*(math.cos(math.radians(-self.options.angle)-math.atan2(cy, cx))) + objlist.append([distance,id]) + elif self.options.direction == "ro": + distance = math.hypot(midx - cx, midy - cy) + objlist.append([distance,id]) + elif self.options.direction == "ri": + distance = -math.hypot(midx - cx, midy - cy) + objlist.append([distance,id]) + + objlist.sort() + #move them to the top of the object stack in this order. + for item in objlist: + parentnode.append( objects[item[1]]) + + def restack_z_order(self): + parentnode = None + objects = [] + if len(self.selected) == 1: + firstobject = self.selected[self.options.ids[0]] + if firstobject.tag == inkex.addNS('g', 'svg'): + parentnode = firstobject + for child in parentnode.iterchildren(reversed=False): + objects.append(child) + else: + parentnode = self.current_layer + for id_ in zSort(self.document.getroot(), self.selected.keys()): + objects.append(self.selected[id_]) + if self.options.zsort == "rev": + objects.reverse() + elif self.options.zsort == "rand": + random.shuffle(objects) + if parentnode is not None: + for item in objects: + parentnode.append(item) + if __name__ == '__main__': e = Restack() |
