changed width slightly
[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_ever_page(t.model, pagenr_objects)
44       end
45       t.undo = function (t, doc)
46          -- no undo possible..
47       end
48       model:register(t)
49    end
50 end
51
52 ----------------------------------------------------------------------
53 -- find pagenumber objects -------------------------------------------
54
55 function find_pagenr_objects(model)
56    res = {}
57    p1 = model.doc[1]
58    for i, obj, sel, layer in p1:objects() do
59       -- find layer called format_layer
60       if layer == format_layer then
61          if obj:type() == "text" then
62             res[#res+1] = obj
63          end
64       end
65    end
66    
67    return res
68 end
69
70 ----------------------------------------------------------------------
71 -- print given pagenumber objects on every page ----------------------
72
73 function print_on_ever_page(model, pagenr_objects)
74    local doc = model.doc
75    -- print "copy.."
76    -- first create the clones
77    -- print "create clones"
78    local clones = {}
79    for i = 1, #doc do
80       local clone_objs = {}
81       for j, obj in ipairs(pagenr_objects) do
82          clone_objs[j] = obj:clone()
83          -- print (i, j, clone_objs[j])
84       end
85       clones[i] = clone_objs
86    end
87    
88    -- then add the clones
89    local pagenr = 0
90    for i = 1, #doc do
91       -- print("get page", i)
92       local p = doc[i]
93       
94       -- increase the pagenr, if the current page does not contain the
95       -- dont_count layer
96       if not page_has_layer(p, dont_count_layer) then
97          pagenr = pagenr + 1
98       end
99
100       -- if the layer does not exists, create it
101       -- print "create layer"
102       if not page_has_layer(p, pagenr_layer) then
103          p:addLayer(pagenr_layer)
104          make_layer_visible(p, pagenr_layer)
105       end
106       
107       -- lock the layer
108       p:setLocked(pagenr_layer, true)
109
110       -- remove all objects from the layer
111       clear_layer(p, pagenr_layer)
112
113       -- add the pagenumbers to the layer
114       -- print "add pagenumbers"
115       for j = 1, #pagenr_objects do
116          -- print (i, j, clones[i][j])
117          -- print(string.gsub(clones[i][j]:text(), page_wildcard, pagenr))
118          local repl_text = clones[i][j]:text():gsub(page_wildcard, pagenr)
119          clones[i][j]:setText(repl_text)
120          p:insert(nil, clones[i][j], nil, pagenr_layer)
121       end
122    end
123 end
124
125 ----------------------------------------------------------------------
126 -- some helper function ----------------------------------------------
127
128 -- make a layer visible on all vies of a page
129 function make_layer_visible(p, layer)
130    for i = 1, p:countViews() do
131       p:setVisible(i, layer, true)
132    end
133 end
134
135 -- remove all objects in a given layer
136 function clear_layer(p, layer)
137    local i = 1
138    while i <= #p do
139       if p:layerOf(i) == layer then
140          p:remove(i)
141       else
142          i = i + 1
143       end
144    end
145 end
146
147 -- returns true if and only if the page p contains the given layer
148 function page_has_layer(p, layer)
149    for _, layer_ in ipairs(p:layers()) do
150       if layer == layer_ then
151          return true
152       end
153    end
154    return false
155 end
156
157 ----------------------------------------------------------------------
158 -- show some message if someone clicks in the iplet menu -------------
159 function run()
160    ipeui.messageBox(nil,
161                     "information",
162                     "Nothing to do here.",
163                     [[
164 This ipelet is used differently...
165 todo: add some text]],
166                     nil)
167 end
168
169 ----------------------------------------------------------------------