Minor changes
[Misc/ipe.git] / ipelets / scale / scale.lua
1
2 --------------------------------------------------------------------------------
3 -- working with groups ---------------------------------------------------------
4
5 local function regroup(elem)
6    local groupElem = {}
7    for i, obj in ipairs(elem) do
8       if obj[1] ~= nil then
9          groupElem[#groupElem + 1] =  regroup(obj)
10       else 
11          groupElem[#groupElem + 1] = obj
12       end
13    end
14    local res = ipe.Group(groupElem)
15    res:setMatrix(elem["matrix"])
16    return res
17 end
18
19 local function ungroup(group)
20    local elem = group:elements()
21    elem["matrix"] = group:matrix()
22    local plainElem = {}
23    for i, obj in ipairs(elem) do
24       if (obj:type() == "group") then
25          local subElem, subPlainElem = ungroup(obj)
26          elem[i] = subElem;
27          for _, subObj in ipairs(subPlainElem) do
28             table.insert(plainElem, subObj)
29          end
30       else
31          table.insert(plainElem, obj)
32       end
33    end
34    return elem, plainElem
35 end
36
37 -- Applies the function func to the object page[obj_id].  If
38 -- page[obj_id] is a group, func is recursively applied to every
39 -- element in this group.
40 function apply_recursively(page, obj_id, funct)
41    obj = page[obj_id]
42    if obj:type() == "group" then
43       local elem, plainElem = ungroup(obj)
44       for _,subobj in pairs(plainElem) do
45          funct(subobj)
46       end
47       page:replace(obj_id, regroup(elem))
48    else
49       funct(obj)
50    end      
51 end
52
53 ----------------------------------------------------------------------
54 -- scaling the usually unscalable ------------------------------------
55
56
57 -- Returns the property of an object like to the get() method.  If
58 -- obj:get(property) returns a number, then this is returned.
59 -- Otherwise, if it returns a symbolic value (like normal, large,
60 -- ...), the corresponding numerical value is looked up (where kind is
61 -- the symbol-type).
62 function get_number(model, obj, property, kind)
63    local res = obj:get(property)
64    if (_G.type(res) == "number") then
65       return res
66    else
67       local sheets = model.doc:sheets()
68       return sheets:find(kind, res)
69    end
70 end
71
72 -- Scale the given property.
73 function scale_property(model, obj, property, kind, factor)
74    obj:set(property, get_number(model, obj, property, kind) * factor)
75 end
76
77 -- Scale symbol size, pen size and arrowsize.
78 function scale_unscalable(model, obj, factor)
79    if (obj:type() == "reference") then
80       scale_property(model, obj, "symbolsize", "symbolsize", factor)
81    end
82    if (obj:type() == "path") then
83       scale_property(model, obj, "pen", "pen", factor)
84       scale_property(model, obj, "farrowsize", "arrowsize", factor)
85       scale_property(model, obj, "rarrowsize", "arrowsize", factor)
86    end
87 end
88
89 -- Scale symbol size, pen size, and arrowsize of the selection.
90 function scale_selection (model)
91    local str = model:getString("Enter scale factor")
92    if not str or str:match("^%s*$") or not str:match("^[%+%-%d%.]+$") then
93       return
94    end
95    local factor = tonumber(str)
96    local p = model:page()
97    local t = { label = "scaling",
98                pno = model.pno,
99                vno = model.vno,
100                selection = model:selection(),
101                original = model:page():clone(),
102                matrix = matrix,
103                undo = _G.revertOriginal,}
104    t.redo = function (t, doc)
105       local p = doc[t.pno]
106       -- for _, i in ipairs(t.selection) do
107       --         p:setSelect(i, 2)
108       -- end
109       local p = doc[t.pno]
110       for i, obj, sel, layer in p:objects() do
111          if sel then
112             apply_recursively(p, i, function (obj) scale_unscalable(model, obj, factor) end)
113          end        
114       end
115    end
116    model:register(t)
117 end
118
119
120
121 label = "Scale"
122 methods = {
123   { label = "scale the unscalable", run=scale_selection },
124 }