first version of the scaling ipelet
[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
55
56 -- Helper for compatibility with different ipe-versions.
57 function mainWindow(model)
58    if model.ui.win == nil then
59       return model.ui
60    else
61       return model.ui:win()
62    end
63 end
64
65 -- Show a warning to the user.
66 function report_problem(model, text)
67    ipeui.messageBox(mainWindow(model), "warning", text, nil, nil)
68 end
69
70 function get_number(model, obj, property, kind)
71    local res = obj:get(property)
72    if (_G.type(res) == "number") then
73       return res
74    else
75       local sheets = model.doc:sheets()
76       return sheets:find(kind, res)
77    end
78 end
79
80 function scale_property(model, obj, property, kind, factor)
81    obj:set(property, get_number(model, obj, property, kind) * factor)
82 end
83
84 function scale_unscalable(model, obj, factor)
85    if (obj:type() == "reference") then
86       scale_property(model, obj, "symbolsize", "symbolsize", factor)
87    end
88    if (obj:type() == "path") then
89       scale_property(model, obj, "pen", "pen", factor)
90       scale_property(model, obj, "farrowsize", "arrowsize", factor)
91       scale_property(model, obj, "rarrowsize", "arrowsize", factor)
92    end
93 end
94
95 function scale_test (model)
96    local p = model:page()
97    local str = model:getString("Enter scale factor")
98    if not str or str:match("^%s*$") or not str:match("^[%+%-%d%.]+$") then
99       return
100    end
101    local factor = tonumber(str)
102     
103    local t = { label = "scaling",
104                pno = model.pno,
105                vno = model.vno,
106                selection = model:selection(),
107                original = model:page():clone(),
108                matrix = matrix,
109                undo = _G.revertOriginal,}
110    t.redo = function (t, doc)
111       local p = doc[t.pno]
112       -- for _, i in ipairs(t.selection) do
113       --         p:setSelect(i, 2)
114       -- end
115       local p = doc[t.pno]
116       for i, obj, sel, layer in p:objects() do
117          if sel then
118             apply_recursively(p, i, function (obj) scale_unscalable(model, obj, factor) end)
119          end        
120       end
121    end
122    model:register(t)
123 end
124
125
126
127 label = "scale_test"
128 methods = {
129   { label = "scale_test", run=scale_test },
130 }