updated readme for decorator
[Misc/ipe.git] / ipelets / pagenumbers / pagenumbers.lua
1 ----------------------------------------------------------------------
2 -- pagenumbers ipelet
3 ----------------------------------------------------------------------
4 label = "Pagenumbers"
5
6 about = [[ An Ipelet for printing customizable pagenumbers to the pages. ]]
7
8 local prefix = "pagenumbers"
9 local format_layer = prefix .. "_format"
10 local pagenr_layer = prefix .. "_page"
11 local dont_count_layer = prefix .. "_dont_count"
12
13 local page_wildcard = "%[page%]" -- ignore the %
14
15 ----------------------------------------------------------------------
16 -- adding page numbers before every run of latex ---------------------
17
18 -- saving the old function
19 function _G.MODEL:pagenumbers_backup_runLatex() end
20 _G.MODEL.pagenumbers_backup_runLatex = _G.MODEL.runLatex
21
22 function _G.MODEL:runLatex()
23    refresh_pagenumbers(self)
24    return self:pagenumbers_backup_runLatex()
25 end
26
27
28 ----------------------------------------------------------------------
29 -- refresh the page numbers ------------------------------------------
30
31 function refresh_pagenumbers(model)
32    -- first find the pagenumber objects that should be printed on
33    -- every page
34    local pagenr_objects = find_pagenr_objects(model)
35
36    -- if something was found, print the page numbers on every page
37    if #pagenr_objects > 0 then
38       -- using the undo-redo construct although there is nothing to
39       -- undo (otherwise, the view does not refresh correctly)
40       local t = { label = "refresh pagenumbers (not undoable)",
41                   model = model }
42       t.redo = function (t, doc)
43          print_on_every_page(t.model, pagenr_objects)
44       end
45       t.undo = function (t, doc)
46          -- no undo possible..
47       end
48       -- model:register(t)
49       print_on_every_page(model, pagenr_objects)
50    end
51 end
52
53 ----------------------------------------------------------------------
54 -- find pagenumber objects -------------------------------------------
55
56 function find_pagenr_objects(model)
57    res = {}
58    p1 = model.doc[1]
59    for i, obj, sel, layer in p1:objects() do
60       -- find layer called format_layer
61       if layer == format_layer then
62          if obj:type() == "text" then
63             res[#res+1] = obj
64          end
65       end
66    end
67    
68    return res
69 end
70
71 ----------------------------------------------------------------------
72 -- print given pagenumber objects on every page ----------------------
73
74 function print_on_every_page(model, pagenr_objects)
75    local doc = model.doc
76    -- print "copy.."
77    -- first create the clones
78    -- print "create clones"
79    local clones = {}
80    for i = 1, #doc do
81       local clone_objs = {}
82       for j, obj in ipairs(pagenr_objects) do
83          clone_objs[j] = obj:clone()
84          -- print (i, j, clone_objs[j])
85       end
86       clones[i] = clone_objs
87    end
88    
89    -- then add the clones
90    local pagenr = 0
91    for i = 1, #doc do
92       -- print("get page", i)
93       local p = doc[i]
94       
95       -- increase the pagenr, if the current page does not contain the
96       -- dont_count layer
97       if not page_has_layer(p, dont_count_layer) then
98          pagenr = pagenr + 1
99       end
100
101       -- if the layer does not exists, create it
102       -- print "create layer"
103       if not page_has_layer(p, pagenr_layer) then
104          p:addLayer(pagenr_layer)
105          make_layer_visible(p, pagenr_layer)
106       end
107       
108       -- lock the layer
109       p:setLocked(pagenr_layer, true)
110
111       -- remove all objects from the layer
112       clear_layer(p, pagenr_layer)
113
114       -- add the pagenumbers to the layer
115       -- print "add pagenumbers"
116       for j = 1, #pagenr_objects do
117          -- print (i, j, clones[i][j])
118          -- print(string.gsub(clones[i][j]:text(), page_wildcard, pagenr))
119          local repl_text = clones[i][j]:text():gsub(page_wildcard, pagenr)
120          clones[i][j]:setText(repl_text)
121          p:insert(nil, clones[i][j], nil, pagenr_layer)
122       end
123    end
124 end
125
126 ----------------------------------------------------------------------
127 -- some helper function ----------------------------------------------
128
129 -- make a layer visible on all vies of a page
130 function make_layer_visible(p, layer)
131    for i = 1, p:countViews() do
132       p:setVisible(i, layer, true)
133    end
134 end
135
136 -- remove all objects in a given layer
137 function clear_layer(p, layer)
138    local i = 1
139    while i <= #p do
140       if p:layerOf(i) == layer then
141          p:remove(i)
142       else
143          i = i + 1
144       end
145    end
146 end
147
148 -- returns true if and only if the page p contains the given layer
149 function page_has_layer(p, layer)
150    for _, layer_ in ipairs(p:layers()) do
151       if layer == layer_ then
152          return true
153       end
154    end
155    return false
156 end
157
158 ----------------------------------------------------------------------
159 -- show some message if someone clicks in the iplet menu -------------
160 function run()
161    ipeui.messageBox(nil,
162                     "information",
163                     "Nothing to do here.",
164                     [[Information on how to use this ipelet can be found in the Ipe Wiki.
165  (https://github.com/otfried/ipelets/tree/master/pagenumbers)
166 ]],
167                     nil)
168 end
169
170 ----------------------------------------------------------------------