1 package featurecat.lizzie.gui; 2 3 import static java.awt.event.KeyEvent.*; 4 5 import featurecat.lizzie.Lizzie; 6 import java.awt.event.*; 7 import javax.swing.*; 8 9 public class Input implements MouseListener, KeyListener, MouseWheelListener, MouseMotionListener { 10 @Override mouseClicked(MouseEvent e)11 public void mouseClicked(MouseEvent e) {} 12 13 @Override mousePressed(MouseEvent e)14 public void mousePressed(MouseEvent e) { 15 if (e.getButton() == MouseEvent.BUTTON1) // left click 16 Lizzie.frame.onClicked(e.getX(), e.getY()); 17 else if (e.getButton() == MouseEvent.BUTTON3) // right click 18 undo(); 19 } 20 21 @Override mouseReleased(MouseEvent e)22 public void mouseReleased(MouseEvent e) {} 23 24 @Override mouseEntered(MouseEvent e)25 public void mouseEntered(MouseEvent e) {} 26 27 @Override mouseExited(MouseEvent e)28 public void mouseExited(MouseEvent e) {} 29 30 @Override mouseDragged(MouseEvent e)31 public void mouseDragged(MouseEvent e) { 32 Lizzie.frame.onMouseDragged(e.getX(), e.getY()); 33 } 34 35 @Override mouseMoved(MouseEvent e)36 public void mouseMoved(MouseEvent e) { 37 Lizzie.frame.onMouseMoved(e.getX(), e.getY()); 38 } 39 40 @Override keyTyped(KeyEvent e)41 public void keyTyped(KeyEvent e) {} 42 undo()43 public static void undo() { 44 undo(1); 45 } 46 undo(int movesToAdvance)47 public static void undo(int movesToAdvance) { 48 if (Lizzie.board.inAnalysisMode()) Lizzie.board.toggleAnalysis(); 49 if (Lizzie.frame.isPlayingAgainstLeelaz) { 50 Lizzie.frame.isPlayingAgainstLeelaz = false; 51 } 52 if (Lizzie.frame.incrementDisplayedBranchLength(-movesToAdvance)) { 53 return; 54 } 55 56 for (int i = 0; i < movesToAdvance; i++) Lizzie.board.previousMove(); 57 } 58 undoToChildOfPreviousWithVariation()59 private void undoToChildOfPreviousWithVariation() { 60 // Undo until the position just after the junction position. 61 // If we are already on such a position, we go to 62 // the junction position for convenience. 63 // Use cases: 64 // [Delete branch] Call this function and then deleteMove. 65 // [Go to junction] Call this function twice. 66 if (!Lizzie.board.undoToChildOfPreviousWithVariation()) Lizzie.board.previousMove(); 67 } 68 undoToFirstParentWithVariations()69 private void undoToFirstParentWithVariations() { 70 if (Lizzie.board.undoToChildOfPreviousWithVariation()) { 71 Lizzie.board.previousMove(); 72 } 73 } 74 goCommentNode(boolean moveForward)75 private void goCommentNode(boolean moveForward) { 76 if (moveForward) { 77 redo(Lizzie.board.getHistory().getCurrentHistoryNode().goToNextNodeWithComment()); 78 } else { 79 undo(Lizzie.board.getHistory().getCurrentHistoryNode().goToPreviousNodeWithComment()); 80 } 81 } 82 redo()83 private void redo() { 84 redo(1); 85 } 86 redo(int movesToAdvance)87 private void redo(int movesToAdvance) { 88 if (Lizzie.board.inAnalysisMode()) Lizzie.board.toggleAnalysis(); 89 if (Lizzie.frame.isPlayingAgainstLeelaz) { 90 Lizzie.frame.isPlayingAgainstLeelaz = false; 91 } 92 if (Lizzie.frame.incrementDisplayedBranchLength(movesToAdvance)) { 93 return; 94 } 95 96 for (int i = 0; i < movesToAdvance; i++) Lizzie.board.nextMove(); 97 } 98 startTemporaryBoard()99 private void startTemporaryBoard() { 100 if (Lizzie.config.showBestMoves) { 101 startRawBoard(); 102 } else { 103 Lizzie.config.showBestMovesTemporarily = true; 104 } 105 } 106 startRawBoard()107 private void startRawBoard() { 108 if (!Lizzie.config.showRawBoard) { 109 Lizzie.frame.startRawBoard(); 110 } 111 Lizzie.config.showRawBoard = true; 112 } 113 stopRawBoard()114 private void stopRawBoard() { 115 Lizzie.frame.stopRawBoard(); 116 Lizzie.config.showRawBoard = false; 117 } 118 stopTemporaryBoard()119 private void stopTemporaryBoard() { 120 stopRawBoard(); 121 Lizzie.config.showBestMovesTemporarily = false; 122 } 123 toggleHints()124 private void toggleHints() { 125 Lizzie.config.toggleShowBranch(); 126 Lizzie.config.showSubBoard = 127 Lizzie.config.showNextMoves = Lizzie.config.showBestMoves = Lizzie.config.showBranch; 128 } 129 nextBranch()130 private void nextBranch() { 131 if (Lizzie.frame.isPlayingAgainstLeelaz) { 132 Lizzie.frame.isPlayingAgainstLeelaz = false; 133 } 134 Lizzie.board.nextBranch(); 135 } 136 previousBranch()137 private void previousBranch() { 138 if (Lizzie.frame.isPlayingAgainstLeelaz) { 139 Lizzie.frame.isPlayingAgainstLeelaz = false; 140 } 141 Lizzie.board.previousBranch(); 142 } 143 moveBranchUp()144 private void moveBranchUp() { 145 Lizzie.board.moveBranchUp(); 146 } 147 moveBranchDown()148 private void moveBranchDown() { 149 Lizzie.board.moveBranchDown(); 150 } 151 deleteMove()152 private void deleteMove() { 153 Lizzie.board.deleteMove(); 154 } 155 deleteBranch()156 private void deleteBranch() { 157 Lizzie.board.deleteBranch(); 158 } 159 controlIsPressed(KeyEvent e)160 private boolean controlIsPressed(KeyEvent e) { 161 boolean mac = System.getProperty("os.name", "").toUpperCase().startsWith("MAC"); 162 return e.isControlDown() || (mac && e.isMetaDown()); 163 } 164 toggleShowDynamicKomi()165 private void toggleShowDynamicKomi() { 166 Lizzie.config.showDynamicKomi = !Lizzie.config.showDynamicKomi; 167 } 168 169 @Override keyPressed(KeyEvent e)170 public void keyPressed(KeyEvent e) { 171 // If any controls key is pressed, let's disable analysis mode. 172 // This is probably the user attempting to exit analysis mode. 173 boolean shouldDisableAnalysis = true; 174 175 switch (e.getKeyCode()) { 176 case VK_E: 177 Lizzie.frame.toggleGtpConsole(); 178 break; 179 case VK_RIGHT: 180 if (e.isShiftDown()) { 181 moveBranchDown(); 182 } else { 183 nextBranch(); 184 } 185 break; 186 187 case VK_LEFT: 188 if (e.isShiftDown()) { 189 moveBranchUp(); 190 } else if (controlIsPressed(e)) { 191 undoToFirstParentWithVariations(); 192 } else { 193 previousBranch(); 194 } 195 break; 196 197 case VK_UP: 198 if (controlIsPressed(e) && e.isShiftDown()) { 199 goCommentNode(false); 200 } else if (e.isShiftDown()) { 201 undoToChildOfPreviousWithVariation(); 202 } else if (controlIsPressed(e)) { 203 undo(10); 204 } else { 205 undo(); 206 } 207 break; 208 209 case VK_PAGE_DOWN: 210 if (controlIsPressed(e) && e.isShiftDown()) { 211 Lizzie.frame.increaseMaxAlpha(-5); 212 } else { 213 redo(10); 214 } 215 break; 216 217 case VK_DOWN: 218 if (controlIsPressed(e) && e.isShiftDown()) { 219 goCommentNode(true); 220 } else if (controlIsPressed(e)) { 221 redo(10); 222 } else { 223 redo(); 224 } 225 break; 226 227 case VK_N: 228 // stop the ponder 229 if (Lizzie.leelaz.isPondering()) Lizzie.leelaz.togglePonder(); 230 LizzieFrame.startNewGame(); 231 break; 232 case VK_SPACE: 233 if (Lizzie.frame.isPlayingAgainstLeelaz) { 234 Lizzie.frame.isPlayingAgainstLeelaz = false; 235 Lizzie.leelaz.isThinking = false; 236 } 237 Lizzie.leelaz.togglePonder(); 238 break; 239 240 case VK_P: 241 Lizzie.board.pass(); 242 break; 243 244 case VK_COMMA: 245 if (!Lizzie.frame.playCurrentVariation()) Lizzie.frame.playBestMove(); 246 break; 247 248 case VK_M: 249 if (e.isAltDown()) { 250 Lizzie.frame.openChangeMoveDialog(); 251 } else { 252 Lizzie.config.toggleShowMoveNumber(); 253 } 254 break; 255 256 case VK_F: 257 Lizzie.config.toggleShowNextMoves(); 258 break; 259 260 case VK_H: 261 Lizzie.config.toggleHandicapInsteadOfWinrate(); 262 break; 263 264 case VK_PAGE_UP: 265 if (controlIsPressed(e) && e.isShiftDown()) { 266 Lizzie.frame.increaseMaxAlpha(5); 267 } else { 268 undo(10); 269 } 270 break; 271 272 case VK_I: 273 // stop the ponder 274 if (Lizzie.leelaz.isPondering()) Lizzie.leelaz.togglePonder(); 275 Lizzie.frame.editGameInfo(); 276 break; 277 case VK_S: 278 // stop the ponder 279 if (Lizzie.leelaz.isPondering()) Lizzie.leelaz.togglePonder(); 280 LizzieFrame.saveFile(); 281 break; 282 283 case VK_O: 284 if (Lizzie.leelaz.isPondering()) Lizzie.leelaz.togglePonder(); 285 LizzieFrame.openFile(); 286 break; 287 288 case VK_V: 289 if (controlIsPressed(e)) { 290 Lizzie.frame.pasteSgf(); 291 } else { 292 Lizzie.config.toggleShowBranch(); 293 } 294 break; 295 296 case VK_HOME: 297 if (controlIsPressed(e)) { 298 Lizzie.board.clear(); 299 } else { 300 while (Lizzie.board.previousMove()) ; 301 } 302 break; 303 304 case VK_END: 305 while (Lizzie.board.nextMove()) ; 306 break; 307 308 case VK_X: 309 if (controlIsPressed(e)) { 310 Lizzie.frame.openConfigDialog(); 311 } else { 312 if (!Lizzie.frame.showControls) { 313 if (Lizzie.leelaz.isPondering()) { 314 wasPonderingWhenControlsShown = true; 315 Lizzie.leelaz.togglePonder(); 316 } else { 317 wasPonderingWhenControlsShown = false; 318 } 319 Lizzie.frame.drawControls(); 320 } 321 Lizzie.frame.showControls = true; 322 } 323 break; 324 325 case VK_W: 326 if (controlIsPressed(e)) { 327 Lizzie.config.toggleLargeWinrate(); 328 } else { 329 Lizzie.config.toggleShowWinrate(); 330 } 331 break; 332 333 case VK_L: 334 Lizzie.config.toggleShowLcbWinrate(); 335 break; 336 337 case VK_G: 338 Lizzie.config.toggleShowVariationGraph(); 339 break; 340 341 case VK_T: 342 if (controlIsPressed(e)) { 343 Lizzie.config.toggleShowCommentNodeColor(); 344 } else { 345 Lizzie.config.toggleShowComment(); 346 } 347 break; 348 349 case VK_Y: 350 Lizzie.config.toggleNodeColorMode(); 351 break; 352 353 case VK_C: 354 if (controlIsPressed(e)) { 355 Lizzie.frame.copySgf(); 356 } else { 357 Lizzie.config.toggleCoordinates(); 358 } 359 break; 360 361 case VK_ENTER: 362 if (!Lizzie.leelaz.isThinking) { 363 Lizzie.leelaz.sendCommand( 364 "time_settings 0 " 365 + Lizzie.config 366 .config 367 .getJSONObject("leelaz") 368 .getInt("max-game-thinking-time-seconds") 369 + " 1"); 370 Lizzie.frame.playerIsBlack = !Lizzie.board.getData().blackToPlay; 371 Lizzie.frame.isPlayingAgainstLeelaz = true; 372 Lizzie.leelaz.genmove((Lizzie.board.getData().blackToPlay ? "B" : "W")); 373 } 374 break; 375 376 case VK_DELETE: 377 case VK_BACK_SPACE: 378 if (e.isShiftDown()) { 379 deleteBranch(); 380 } else { 381 deleteMove(); 382 } 383 break; 384 385 case VK_Z: 386 if (e.isShiftDown()) { 387 toggleHints(); 388 } else { 389 startTemporaryBoard(); 390 } 391 break; 392 393 case VK_A: 394 shouldDisableAnalysis = false; 395 Lizzie.board.toggleAnalysis(); 396 break; 397 398 case VK_PERIOD: 399 if (!Lizzie.board.getHistory().getNext().isPresent()) { 400 Lizzie.board.setScoreMode(!Lizzie.board.inScoreMode()); 401 } 402 break; 403 404 case VK_D: 405 toggleShowDynamicKomi(); 406 break; 407 408 case VK_R: 409 Lizzie.frame.replayBranch(); 410 break; 411 412 case VK_OPEN_BRACKET: 413 if (Lizzie.frame.BoardPositionProportion > 0) Lizzie.frame.BoardPositionProportion--; 414 break; 415 416 case VK_CLOSE_BRACKET: 417 if (Lizzie.frame.BoardPositionProportion < 8) Lizzie.frame.BoardPositionProportion++; 418 break; 419 420 case VK_K: 421 Lizzie.config.toggleEvaluationColoring(); 422 break; 423 424 // Use Ctrl+Num to switching multiple engine 425 case VK_0: 426 case VK_1: 427 case VK_2: 428 case VK_3: 429 case VK_4: 430 case VK_5: 431 case VK_6: 432 case VK_7: 433 case VK_8: 434 case VK_9: 435 if (controlIsPressed(e)) { 436 Lizzie.switchEngine(e.getKeyCode() - VK_0); 437 } 438 break; 439 default: 440 shouldDisableAnalysis = false; 441 } 442 443 if (shouldDisableAnalysis && Lizzie.board.inAnalysisMode()) Lizzie.board.toggleAnalysis(); 444 445 Lizzie.frame.repaint(); 446 } 447 448 private boolean wasPonderingWhenControlsShown = false; 449 450 @Override keyReleased(KeyEvent e)451 public void keyReleased(KeyEvent e) { 452 switch (e.getKeyCode()) { 453 case VK_X: 454 if (wasPonderingWhenControlsShown) Lizzie.leelaz.togglePonder(); 455 Lizzie.frame.showControls = false; 456 Lizzie.frame.repaint(); 457 break; 458 459 case VK_Z: 460 stopTemporaryBoard(); 461 Lizzie.frame.repaint(); 462 break; 463 464 default: 465 } 466 } 467 468 @Override mouseWheelMoved(MouseWheelEvent e)469 public void mouseWheelMoved(MouseWheelEvent e) { 470 if (Lizzie.frame.processCommentMouseWheelMoved(e)) { 471 return; 472 } 473 if (Lizzie.board.inAnalysisMode()) Lizzie.board.toggleAnalysis(); 474 if (e.getWheelRotation() > 0) { 475 redo(); 476 } else if (e.getWheelRotation() < 0) { 477 undo(); 478 } 479 Lizzie.frame.repaint(); 480 } 481 } 482