X-Git-Url: https://i11git.iti.kit.edu/anon-gitweb/?p=Misc%2Fipe.git;a=blobdiff_plain;f=ipelets%2Fdecorator%2Fdecorator.lua;h=2c25d248444575d6f16ab786c0b6f457b6a3c27d;hp=389a26060d1cd1774212d2a8e445c1a9f20e1098;hb=9eb44c913e8080afa75a13864875111ec15c42a6;hpb=3c74c6209065a27ce5bfab85c0164bd826301357 diff --git a/ipelets/decorator/decorator.lua b/ipelets/decorator/decorator.lua index 389a260..2c25d24 100644 --- a/ipelets/decorator/decorator.lua +++ b/ipelets/decorator/decorator.lua @@ -1,15 +1,11 @@ --- return a table of names associated with decorator symbols -function decorator_names(model) - local sheets = model.doc:sheets() - local symbols = sheets:allNames("symbol") - local res = {} - for _, name in pairs(symbols) do - if name:find("deco/") == 1 then - res[#res + 1] = name - end +-- Helper for compatibility with different ipe-versions. +function mainWindow(model) + if model.ui.win == nil then + return model.ui + else + return model.ui:win() end - return res end -- Changes the transformation matrix of a path object to the identitiy @@ -78,6 +74,9 @@ function resize_shape(shape, center, bbox_source, bbox_target) transform_shape(shape, matrix_func) end +-- Bounding box of a given object that is not currently contained in +-- the page. If the object is already part of the page, simply use +-- p:bbox(obj). function bbox(obj, page) local objno = #page + 1 page:insert(objno, obj, nil, page:layers()[1]) @@ -86,25 +85,71 @@ function bbox(obj, page) return bbox end +-- The bounding box of all selected objects. +function bbox_of_selected_objects(page) + local bbox = page:bbox(page:primarySelection()) + for obj = 1, #page, 1 do + if page:select(obj) then + bbox:add(page:bbox(obj)) + end + end + return bbox +end + +-- Show a warning to the user. function report_problem(model, text) ipeui.messageBox(mainWindow(model), "warning", text, nil, nil) end -function run_fancy_decorator (model) +-- Return a table of names associated with decorator symbols. +function decorator_names(model) + local sheets = model.doc:sheets() + local symbols = sheets:allNames("symbol") + local res = {} + for _, name in pairs(symbols) do + if name:find("deco/") == 1 then + res[#res + 1] = name + end + end + return res +end + +-- Check whether a given deco object is usable. +function check_decorator_object(model, deco_obj_group) + if (deco_obj_group:type() ~= "group") then + report_problem(model, "The decoration must be a group.") + return false + end + + local objects = deco_obj_group:elements() + local last_obj = table.remove(objects, #objects) + if (#objects == 0) then + report_problem(model, "The decoration must be a group of at least two elements (the topmost element is a placeholder for the objects that are decorated, all other elements are the decoration).") + return false + end + + for i,deco_obj in ipairs(objects) do + if (deco_obj:type() ~= "path") then + report_problem(model, "Each decoration object needs to be a path.") + return false + end + end + return true +end + +-- Ask the user for a decorator and run the decoration. +function run_decorator (model) local p = model:page() local prim = p:primarySelection() if (not prim) then report_problem(model, "You must select somethings.") return end - local bbox_target = p:bbox(prim) + local bbox_target = bbox_of_selected_objects(p) local deco_obj_group = ask_for_decorator(model) - if (not deco_obj_group) then return end - if (deco_obj_group:type() ~= "group") then - report_problem(model, "The decoration must be a group.") - return - end + if (not deco_obj_group) then return end + if (not check_decorator_object(model, deco_obj_group)) then return end local objects = deco_obj_group:elements() local last_obj = table.remove(objects, #objects) @@ -112,16 +157,7 @@ function run_fancy_decorator (model) local center = ipe.Vector(bbox_source:left() + 0.5 * bbox_source:width(), bbox_source:bottom() + 0.5 * bbox_source:height()) - if (#objects == 0) then - report_problem(model, "The decoration must be a group of at least two elements.") - return - end for i,deco_obj in ipairs(objects) do - if (deco_obj:type() ~= "path") then - report_problem(model, "Each decoration object needs to be a path.") - return - end - cleanup_matrix(deco_obj) local deco_shape = deco_obj:shape() @@ -132,7 +168,7 @@ function run_fancy_decorator (model) local group = ipe.Group(objects) - model:creation("fancy decoration created", group) + model:creation("decoration created", group) end -- Asks the user for a decorator and returns the chosen decorator @@ -150,15 +186,65 @@ function ask_for_decorator(model) return symbol:clone() end -function mainWindow(model) - if model.ui.win == nil then - return model.ui - else - return model.ui:win() +-- Basically create symbol taken from "symbols.lua" with two minor +-- changes. First, the symbol is created only if the call to +-- check_decorator_object is successful. Second, the prefix "deco/" +-- is added to the symbols name. +function create_deco_obj(model, num) + local p = model:page() + local prim = p:primarySelection() + if not prim then model.ui:explain("no selection") return end + if not check_decorator_object(model, p[prim]) then + model.ui:explain("no selection") + return + end + local str = model:getString("Enter name of new symbol") + if not str or str:match("^%s*$") then return end + local name = "deco/" .. str:match("^%s*%S+%s*$") + local old = model.doc:sheets():find("symbol", name) + if old then + local r = ipeui.messageBox(mainWindow(model), "question", + "Symbol '" .. name .. "' already exists", + "Do you want to proceed?", + "okcancel") + if r <= 0 then return end + end + + if num == 2 then -- new stylesheet + local sheet = ipe.Sheet() + sheet:add("symbol", name, p[prim]) + local t = { label = methods[num].label, + sheet = sheet, + } + t.redo = function (t, doc) + doc:sheets():insert(1, t.sheet:clone()) + end + t.undo = function (t, doc) + doc:sheets():remove(1) + end + model:register(t) + else -- top stylesheet + local sheet = model.doc:sheets():sheet(1) + local t = { label = methods[num].label, + original = sheet:clone(), + final = sheet:clone(), + } + t.final:add("symbol", name, p[prim]) + t.redo = function (t, doc) + doc:sheets():remove(1) + doc:sheets():insert(1, t.final:clone()) + end + t.undo = function (t, doc) + doc:sheets():remove(1) + doc:sheets():insert(1, t.original:clone()) + end + model:register(t) end end label = "Decorator" methods = { - { label = "Fancy decorator", run=run_fancy_decorator}, + { label = "decorate", run=run_decorator }, + { label = "create deco-object (in new style sheet)", run=create_deco_obj }, + { label = "create deco-object (in top style sheet)", run=create_deco_obj }, }