OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
73 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
182 ilm 4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
73 ilm 5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.erp.config;
15
 
16
import org.openconcerto.ui.SwingThreadUtils;
17
import org.openconcerto.ui.group.Group;
18
import org.openconcerto.ui.group.Item;
19
 
20
import java.util.Collections;
21
import java.util.HashMap;
22
import java.util.List;
23
import java.util.Map;
24
 
25
import javax.swing.Action;
26
 
27
import net.jcip.annotations.GuardedBy;
28
import net.jcip.annotations.ThreadSafe;
29
 
30
@ThreadSafe
31
public final class MenuAndActions {
32
 
33
    @GuardedBy("this")
34
    private final Group group;
35
    @GuardedBy("this")
36
    private final Map<String, Action> actions;
37
 
38
    public MenuAndActions() {
39
        this(new Group("menu.main"), Collections.<String, Action> emptyMap());
40
    }
41
 
42
    public MenuAndActions(final Group group, final Map<String, Action> actions) {
43
        this.group = Group.copy(group, null);
156 ilm 44
        this.actions = new HashMap<>(actions);
73 ilm 45
    }
46
 
47
    public final synchronized MenuAndActions copy() {
48
        return new MenuAndActions(this.getGroup(), this.actions);
49
    }
50
 
51
    public final void putAction(final Action a) {
52
        this.putAction(a, null);
53
    }
54
 
55
    public final void putAction(final Action a, final String id) {
56
        this.putAction(a, id, false);
57
    }
58
 
59
    /**
60
     * Add an action.
61
     *
62
     * @param a the action to add.
63
     * @param id the ID, if <code>null</code> taken from the
64
     *        {@link SwingThreadUtils#getActionID(Action) action}.
65
     * @param canReplace <code>true</code> if the passed action can replace an existing one.
66
     * @return the used ID.
67
     */
68
    public final String putAction(final Action a, final String id, final boolean canReplace) {
69
        return this.putAction(a, id, canReplace, false);
70
    }
71
 
72
    private final synchronized String putAction(final Action a, String id, final boolean canReplace, final boolean dryRun) {
73
        if (a == null)
74
            throw new NullPointerException("Null action");
75
        if (id == null)
76
            id = SwingThreadUtils.getActionID(a);
77
        if (id == null)
78
            throw new NullPointerException("Null ID");
79
        if (!canReplace && this.actions.containsKey(id))
80
            throw new IllegalStateException("ID exists : " + this.actions.get(id));
81
        if (!dryRun)
82
            this.actions.put(id, a);
83
        return id;
84
    }
85
 
86
    public final synchronized Action getAction(final String id) {
87
        return this.actions.get(id);
88
    }
89
 
90
    /**
91
     * Return the group modeling the menu.
92
     *
93
     * @return a frozen group.
94
     */
95
    public final synchronized Group getGroup() {
96
        return this.group;
97
    }
98
 
99
    public void addMenuItem(final Action action, final List<String> path) {
100
        this.addMenuItem(action, null, path);
101
    }
102
 
103
    public void addMenuItem(final Action action, final String actionID, final List<String> path) {
104
        this.addMenuItem(action, actionID, path, false);
105
    }
106
 
107
    /**
108
     * Adds a menu item to this menu. The path should be an alternation of menu and group within
109
     * that menu. All items within the same group will be grouped together inside separators. Menus
110
     * will be created as needed.
111
     *
112
     * @param action the action to perform.
113
     * @param actionID ID of the action, see {@link #putAction(Action, String, boolean)}.
114
     * @param path where to add the menu item.
115
     * @param canReplace <code>true</code> if this method can replace an existing action and menu
116
     *        item.
117
     * @return the menu item.
118
     * @throws IllegalArgumentException if path is empty.
119
     * @throws IllegalStateException if <code>actionID</code> already exists in either the menu or
120
     *         the actions.
121
     */
122
    public Item addMenuItem(final Action action, String actionID, final List<String> path, final boolean canReplace) throws IllegalStateException {
156 ilm 123
        if (path.isEmpty())
73 ilm 124
            throw new IllegalArgumentException("Empty path");
125
 
126
        final Item res;
127
        synchronized (this) {
128
            // check actionID
129
            actionID = this.putAction(action, actionID, canReplace, true);
130
 
131
            // check and modify group
132
            final Group groupDesc = this.getGroup().followPath(path, true);
182 ilm 133
            final Item child = groupDesc.getDescFromID(actionID);
73 ilm 134
            if (!canReplace && child != null) {
135
                throw new IllegalStateException("ID exists : " + child);
136
            }
137
            if (child == null) {
138
                res = new Item(actionID);
139
                groupDesc.add(res);
140
            } else {
141
                res = child;
142
            }
143
 
144
            // modify action
145
            this.putAction(action, actionID, canReplace, false);
146
        }
147
        assert res != null;
148
        return res;
149
    }
150
 
151
    public void setMenuItemVisible(final String actionID, final boolean v) {
152
        synchronized (this) {
153
            final Item mi = this.getGroup().getDescFromID(actionID);
154
            mi.setLocalHint(mi.getLocalHint().getBuilder().setVisible(v).build());
155
        }
156
    }
157
}