1%%
2%%  wpc_deselect_previous.erl --
3%%
4%%    Subtract current selection from previous selection.
5%%
6%%  Copyright (c) 2010-2011 Richard Jones.
7%%
8%%  See the file "license.terms" for information on usage and redistribution
9%%  of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10%%
11
12-module(wpc_deselect_previous).
13-export([init/0,menu/2,command/2]).
14-include_lib("src/wings.hrl").
15
16init() ->
17    true.
18
19%%% Menu
20menu({select},Menu) ->
21    lists:reverse(parse(Menu, [], false));
22menu(_,Menu) ->
23    Menu.
24
25parse([], NewMenu, true) ->
26    NewMenu;
27parse([], NewMenu, false) ->
28    [deselect_previous(), separator|NewMenu];
29parse([A = {_,inverse,_}|Rest], NewMenu, false) ->
30    parse(Rest, [deselect_previous(),A|NewMenu], true);
31parse([Elem|Rest], NewMenu, Found) ->
32    parse(Rest, [Elem|NewMenu], Found).
33
34deselect_previous() ->
35    {?__(1,"Deselect Previous"),deselect_previous,
36     ?__(2,"Subtract the previous selection state from the current selection")}.
37
38%%% Commands
39command({select,deselect_previous}, St) ->
40    {save_state,deselect_previous(St)};
41command(_, _) ->
42    next.
43
44deselect_previous(St) ->
45    PrevSt = wings_undo:undo(St),
46    deselect_previous(PrevSt, St).
47
48deselect_previous(#st{sel=PrevSel,selmode=Mode}, #st{sel=Sel,selmode=Mode}=St) ->
49    NewSel = subtract(Sel, PrevSel),
50    St#st{sel=NewSel};
51deselect_previous(PrevSt0, #st{selmode=Mode}=St) ->
52    PrevSt = wings_sel_conv:mode(Mode, PrevSt0),
53    deselect_previous(PrevSt, St).
54
55subtract([{Id1,_}=E1|Es1], [{Id2,_}|_]=Set2) when Id1 < Id2 ->
56    [E1|subtract(Es1, Set2)];
57subtract([{Id1,_}|_]=Set1, [{Id2,_}|Es2]) when Id1 > Id2 ->
58    subtract(Set1, Es2);
59subtract([{Id,E1}|Es1], [{Id,E2}|Es2]) ->
60    E = gb_sets:subtract(E1, E2),
61    case gb_sets:is_empty(E) of
62        true -> subtract(Es1, Es2);
63        false -> [{Id,E}|subtract(Es1, Es2)]
64    end;
65subtract([], _Es2) -> [];
66subtract(Es1, []) -> Es1.
67