| 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 |