1 | // Copyright 2004-2007 Jean-Francois Poilpret |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | package net.sourceforge.hiveboard.dialog; |
16 | |
17 | import java.text.DecimalFormat; |
18 | import java.util.HashSet; |
19 | import java.util.Map; |
20 | import java.util.Set; |
21 | |
22 | import javax.swing.DefaultComboBoxModel; |
23 | import javax.swing.JComboBox; |
24 | import javax.swing.JComponent; |
25 | import javax.swing.JFormattedTextField; |
26 | import javax.swing.JLabel; |
27 | import javax.swing.JScrollPane; |
28 | import javax.swing.JTextField; |
29 | |
30 | import org.jdesktop.application.Action; |
31 | import org.jdesktop.application.Task; |
32 | |
33 | import net.sourceforge.hiveboard.Account; |
34 | import net.sourceforge.hiveboard.Board; |
35 | import net.sourceforge.hiveboard.BoardTokenSetter; |
36 | import net.sourceforge.hiveboard.WhiteBoardUserService; |
37 | import net.sourceforge.hiveboard.command.AbstractTask; |
38 | import net.sourceforge.hiveboard.main.ServerSettingsKeys; |
39 | import net.sourceforge.hivegui.application.HiveGuiApplicationMain; |
40 | import net.sourceforge.hivegui.component.TextListener; |
41 | import net.sourceforge.hivegui.dialog.GenericDialog; |
42 | import net.sourceforge.hivegui.table.BeanTable; |
43 | import net.sourceforge.hivegui.table.DataListModel; |
44 | import net.sourceforge.hivetranse.exception.DuplicateKeyException; |
45 | |
46 | import zappini.designgridlayout.DesignGridLayout; |
47 | import zappini.designgridlayout.Row; |
48 | |
49 | // CSOFF: ClassDataAbstractionCouplingCheck |
50 | public class BoardPanel extends AbstractBoardPanel |
51 | { |
52 | static private final String NAME_CREATE = "board-creation"; |
53 | static private final String NAME_MODIFY = "board-modification"; |
54 | |
55 | public BoardPanel( BeanTable<Account> tblAccounts, |
56 | BoardTokenSetterRenderer renderer, |
57 | WhiteBoardUserService service, |
58 | Map<String, Object> serverSettings) |
59 | { |
60 | this(tblAccounts, renderer, service, serverSettings, null, true); |
61 | } |
62 | |
63 | public BoardPanel( BeanTable<Account> tblAccounts, |
64 | BoardTokenSetterRenderer renderer, |
65 | WhiteBoardUserService service, |
66 | Map<String, Object> serverSettings, |
67 | Board board) |
68 | { |
69 | this(tblAccounts, renderer, service, serverSettings, board.copy(), false); |
70 | } |
71 | |
72 | private BoardPanel( BeanTable<Account> tblAccounts, |
73 | BoardTokenSetterRenderer renderer, |
74 | WhiteBoardUserService service, |
75 | Map<String, Object> serverSettings, |
76 | Board board, |
77 | boolean create) |
78 | { |
79 | super(create ? NAME_CREATE : NAME_MODIFY); |
80 | _service = service; |
81 | _create = create; |
82 | |
83 | _tblAccounts = tblAccounts; |
84 | Integer maxBoardSize = (Integer) serverSettings.get(ServerSettingsKeys.MAX_BOARD_SIZE); |
85 | _maxBoardSize = maxBoardSize.intValue(); |
86 | _board = board; |
87 | _accounts = _tblAccounts.getDataListModel(); |
88 | |
89 | initComponentNames(); |
90 | initComponents(renderer); |
91 | |
92 | _lblName.setLabelFor(_txfName); |
93 | _lblDescription.setLabelFor(_txfDescription); |
94 | _lblWidth.setLabelFor(_txfWidth); |
95 | _lblHeight.setLabelFor(_txfHeight); |
96 | _lblTokenSetter.setLabelFor(_cboTokenSetter); |
97 | _lblParticipants.setLabelFor(_tblAccounts); |
98 | |
99 | DesignGridLayout layout = new DesignGridLayout(this); |
100 | setLayout(layout); |
101 | |
102 | // Add widgets to the panel |
103 | layout.row().label(_lblName).add(_txfName); |
104 | layout.row().label(_lblDescription).add(_txfDescription); |
105 | layout.row().label(_lblWidth).add(_txfWidth).add(Row.EMPTY); |
106 | layout.row().label(_lblHeight).add(_txfHeight).add(Row.EMPTY); |
107 | layout.row().label(_lblTokenSetter).add(_cboTokenSetter); |
108 | layout.row().label(_lblParticipants).add(new JScrollPane(_tblAccounts)); |
109 | } |
110 | |
111 | private void initComponents(BoardTokenSetterRenderer renderer) |
112 | { |
113 | _cboTokenSetter.setModel( |
114 | new DefaultComboBoxModel(BoardTokenSetter.class.getEnumConstants())); |
115 | _cboTokenSetter.setRenderer(renderer); |
116 | |
117 | TextListener listener = new TextListener() |
118 | { |
119 | @Override protected void contentUpdated() |
120 | { |
121 | Number width = (Number) _txfWidth.getValue(); |
122 | Number height = (Number) _txfHeight.getValue(); |
123 | setAcceptEnabled( _txfName.getText() != null |
124 | && _txfName.getText().length() != 0 |
125 | && width != null |
126 | && width.shortValue() > 0 |
127 | && height != null |
128 | && height.shortValue() > 0); |
129 | } |
130 | }; |
131 | |
132 | _txfName.getDocument().addDocumentListener(listener); |
133 | _txfWidth.getDocument().addDocumentListener(listener); |
134 | _txfHeight.getDocument().addDocumentListener(listener); |
135 | if (!_create) |
136 | { |
137 | _txfWidth.setEnabled(false); |
138 | _txfHeight.setEnabled(false); |
139 | } |
140 | } |
141 | |
142 | private void initComponentNames() |
143 | { |
144 | String name = getName(); |
145 | _lblName.setName(name + "-name-label"); |
146 | _txfName.setName(name + "-name"); |
147 | _lblDescription.setName(name + "-description-label"); |
148 | _txfDescription.setName(name + "-description"); |
149 | _lblWidth.setName(name + "-width-label"); |
150 | _txfWidth.setName(name + "-width"); |
151 | _lblHeight.setName(name + "-height-label"); |
152 | _txfHeight.setName(name + "-height"); |
153 | _lblTokenSetter.setName(name + "-token-setter-label"); |
154 | _cboTokenSetter.setName(name + "-token-setter"); |
155 | _lblParticipants.setName(name + "-participants-list-label"); |
156 | _tblAccounts.setName(name + "-participants-list"); |
157 | } |
158 | |
159 | @Override public void reset() |
160 | { |
161 | if (_create) |
162 | { |
163 | // If dialog for board creation, reinitialize a new Board |
164 | _board = new Board(); |
165 | setAcceptEnabled(false); |
166 | } |
167 | refresh(); |
168 | } |
169 | |
170 | @Action(enabledProperty = "acceptEnabled", block = Task.BlockingScope.WINDOW) |
171 | public Task accept() |
172 | { |
173 | if (!checkInput()) |
174 | { |
175 | return null; |
176 | } |
177 | |
178 | updateBoard(); |
179 | |
180 | return new ModifyBoardTask(_application, _parent); |
181 | } |
182 | |
183 | private boolean checkInput() |
184 | { |
185 | JComponent badInputField = null; |
186 | short width = ((Number) _txfWidth.getValue()).shortValue(); |
187 | short height = ((Number) _txfHeight.getValue()).shortValue(); |
188 | if (width > _maxBoardSize) |
189 | { |
190 | badInputField = _txfWidth; |
191 | } |
192 | else if (height > _maxBoardSize) |
193 | { |
194 | badInputField = _txfHeight; |
195 | } |
196 | if (badInputField != null) |
197 | { |
198 | // Display Message |
199 | _application.showMessage("board-size-off-limits", _maxBoardSize); |
200 | badInputField.requestFocusInWindow(); |
201 | return false; |
202 | } |
203 | return true; |
204 | } |
205 | |
206 | private void updateBoard() |
207 | { |
208 | _board.setName(_txfName.getText()); |
209 | _board.setDescription(_txfDescription.getText()); |
210 | _board.setHeight(((Number) _txfHeight.getValue()).shortValue()); |
211 | _board.setWidth(((Number) _txfWidth.getValue()).shortValue()); |
212 | _board.setTokenSetter((BoardTokenSetter) _cboTokenSetter.getSelectedItem()); |
213 | |
214 | Set<Integer> participants = new HashSet<Integer>(); |
215 | int[] selected = _tblAccounts.getSelectedRows(); |
216 | for (int i = 0; i < selected.length; i++) |
217 | { |
218 | Account account = _accounts.getRow(selected[i]); |
219 | participants.add(account.getId()); |
220 | } |
221 | _board.setParticipants(participants); |
222 | } |
223 | |
224 | private void refresh() |
225 | { |
226 | _txfName.setText(_board.getName()); |
227 | _txfDescription.setText(_board.getDescription()); |
228 | _txfWidth.setValue(_board.getWidth()); |
229 | _txfHeight.setValue(_board.getHeight()); |
230 | _cboTokenSetter.setSelectedItem(_board.getTokenSetter()); |
231 | |
232 | // Remove previous selection first |
233 | _tblAccounts.clearSelection(); |
234 | // Set new selection |
235 | Account[] accounts = _accounts.getRows(); |
236 | for (int id: _board.getParticipants()) |
237 | { |
238 | for (int i = 0; i < accounts.length; i++) |
239 | { |
240 | if (accounts[i].getId() == id) |
241 | { |
242 | _tblAccounts.addRowSelectionInterval(i, i); |
243 | break; |
244 | } |
245 | } |
246 | } |
247 | } |
248 | |
249 | private class ModifyBoardTask extends AbstractTask<Void, Void> |
250 | { |
251 | public ModifyBoardTask(HiveGuiApplicationMain application, GenericDialog parent) |
252 | { |
253 | super(application, parent); |
254 | } |
255 | |
256 | @Override protected Void doInBackground() throws Exception |
257 | { |
258 | if (_board.getId() == 0) |
259 | { |
260 | _service.createBoard(_board); |
261 | } |
262 | else |
263 | { |
264 | _service.modifyBoard(_board); |
265 | } |
266 | return null; |
267 | } |
268 | |
269 | @Override protected void failed(Throwable cause) |
270 | { |
271 | if (cause instanceof DuplicateKeyException) |
272 | { |
273 | // Display Message |
274 | _application.showMessage("duplicate-board-name", _board.getName()); |
275 | } |
276 | else |
277 | { |
278 | super.failed(cause); |
279 | } |
280 | } |
281 | } |
282 | |
283 | private final WhiteBoardUserService _service; |
284 | private final boolean _create; |
285 | private final int _maxBoardSize; |
286 | |
287 | private final JLabel _lblName = new JLabel(); |
288 | private final JTextField _txfName = new JTextField(); |
289 | private final JLabel _lblDescription = new JLabel(); |
290 | private final JTextField _txfDescription = new JTextField(); |
291 | private final JLabel _lblWidth = new JLabel(); |
292 | private final JFormattedTextField _txfWidth = new JFormattedTextField( |
293 | new DecimalFormat("####")); |
294 | private final JLabel _lblHeight = new JLabel(); |
295 | private final JFormattedTextField _txfHeight = new JFormattedTextField( |
296 | new DecimalFormat("####")); |
297 | private final JLabel _lblTokenSetter = new JLabel(); |
298 | private final JComboBox _cboTokenSetter = new JComboBox(); |
299 | private final JLabel _lblParticipants = new JLabel(); |
300 | private final BeanTable<Account> _tblAccounts; |
301 | private final DataListModel<Account> _accounts; |
302 | } |
303 | // CSON: ClassDataAbstractionCouplingCheck |