decorator in a usable state
[Misc/ipe.git] / ipelets / decorator / decorator.lua
1
2 -- return a table of names associated with decorator symbols
3 function decorator_names(model)
4    local sheets = model.doc:sheets()
5    local symbols = sheets:allNames("symbol")
6    local res = {}
7    for _, name in pairs(symbols) do
8       if name:find("deco/") == 1 then
9          res[#res + 1] = name
10       end
11    end
12    return res
13 end
14
15 -- Decorate something given by its bounding box with a given deco
16 -- object, which needs to be a path.
17 function decorate(model, bbox, deco)
18    if (deco:type() ~= "path") then
19       model.ui:explain("The decoration needs to be a path.")
20       return
21    end
22
23    local shape = deco:shape()
24    for _,path in pairs(shape) do
25       for _,subpath in ipairs(path) do   
26          -- move all points
27          for i,point in ipairs(subpath) do
28             subpath[i] = translation(bbox, point) * point
29          end
30
31          -- for acs, the center must be translated separately
32          if (subpath["type"] == "arc") then
33             local arc = subpath["arc"]
34             local arc_pos = arc:matrix():translation()
35             subpath["arc"] = translation(bbox, arc_pos) * arc
36          end
37       end
38    end
39    -- update model
40    deco:setShape(shape)
41    model:creation("create", deco)
42 end
43
44 -- The translation matrix that should be applied to a given point when
45 -- doing the decoration.
46 function translation(bbox, point)
47    local dx = 0
48    local dy = 0
49    if (point.x > 0) then
50       dx = dx + bbox:width()
51    end
52    if (point.y > 0) then
53       dy = dy + bbox:height()
54    end
55    dx = dx + bbox:left()
56    dy = dy + bbox:bottom()
57    return ipe.Translation(dx, dy)
58 end
59
60 function mainWindow(model)
61    if model.ui.win == nil then
62       return model.ui
63    else
64       return model.ui:win()
65    end
66 end
67
68 function run_decorator(model)
69    -- get bbox of primary selection
70    local p = model:page()
71    local prim = p:primarySelection()
72    if not prim then
73       model.ui:explain("An object must be selected.")
74       return
75    end
76    local bbox = p:bbox(prim)
77
78    -- create decorator object
79    local dialog = ipeui.Dialog(mainWindow(model), "Select a decorator.")
80    local decorators = decorator_names(model)
81    dialog:add("deco", "combo", decorators, 1, 1, 1, 2)
82    dialog:add("ok", "button", { label="&Ok", action="accept" }, 2, 2)
83    dialog:add("cancel", "button", { label="&Cancel", action="reject" }, 2, 1)
84    local r = dialog:execute()
85    if not r then return end
86    local deco_name = decorators[dialog:get("deco")]
87    local symbol = model.doc:sheets():find("symbol", deco_name)
88    local deco = symbol:clone()
89
90    -- run the decoration
91    decorate(model, bbox, deco)
92 end
93
94 label = "Decorator"
95 methods = {
96   { label = "Decorate", run=run_decorator},
97 }