X-Git-Url: http://git.nikiroo.be/?p=jvcard.git;a=blobdiff_plain;f=src%2Fcom%2Fgooglecode%2Flanterna%2Fgui2%2FInteractableLookupMap.java;fp=src%2Fcom%2Fgooglecode%2Flanterna%2Fgui2%2FInteractableLookupMap.java;h=0000000000000000000000000000000000000000;hp=a200a302f40f6f51fbdd7953f0a8e48086794387;hb=f06c81000632cfb5f525ca458f719338f55f9f66;hpb=a73a906356c971b080c36368e71a15d87e8b8d31 diff --git a/src/com/googlecode/lanterna/gui2/InteractableLookupMap.java b/src/com/googlecode/lanterna/gui2/InteractableLookupMap.java deleted file mode 100644 index a200a30..0000000 --- a/src/com/googlecode/lanterna/gui2/InteractableLookupMap.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This file is part of lanterna (http://code.google.com/p/lanterna/). - * - * lanterna is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * Copyright (C) 2010-2015 Martin - */ -package com.googlecode.lanterna.gui2; - -import com.googlecode.lanterna.TerminalPosition; -import com.googlecode.lanterna.TerminalSize; - -import java.util.*; - -/** - * This class is used to keep a 'map' of the usable area and note where all the interact:ables are. It can then be used - * to find the next interactable in any direction. It is used inside the GUI system to drive arrow key navigation. - * @author Martin - */ -public class InteractableLookupMap { - private final int[][] lookupMap; - private final List interactables; - - InteractableLookupMap(TerminalSize size) { - lookupMap = new int[size.getRows()][size.getColumns()]; - interactables = new ArrayList(); - for (int[] aLookupMap : lookupMap) { - Arrays.fill(aLookupMap, -1); - } - } - - void reset() { - interactables.clear(); - for (int[] aLookupMap : lookupMap) { - Arrays.fill(aLookupMap, -1); - } - } - - TerminalSize getSize() { - if (lookupMap.length==0) { return TerminalSize.ZERO; } - return new TerminalSize(lookupMap[0].length, lookupMap.length); - } - - /** - * Adds an interactable component to the lookup map - * @param interactable Interactable to add to the lookup map - */ - @SuppressWarnings("ConstantConditions") - public synchronized void add(Interactable interactable) { - TerminalPosition topLeft = interactable.toBasePane(TerminalPosition.TOP_LEFT_CORNER); - TerminalSize size = interactable.getSize(); - interactables.add(interactable); - int index = interactables.size() - 1; - for(int y = topLeft.getRow(); y < topLeft.getRow() + size.getRows(); y++) { - for(int x = topLeft.getColumn(); x < topLeft.getColumn() + size.getColumns(); x++) { - //Make sure it's not outside the map - if(y >= 0 && y < lookupMap.length && - x >= 0 && x < lookupMap[y].length) { - lookupMap[y][x] = index; - } - } - } - } - - /** - * Looks up what interactable component is as a particular location in the map - * @param position Position to look up - * @return The {@code Interactable} component at the specified location or {@code null} if there's nothing there - */ - public synchronized Interactable getInteractableAt(TerminalPosition position) { - if(position.getRow() >= lookupMap.length) { - return null; - } - else if(position.getColumn() >= lookupMap[0].length) { - return null; - } - else if(lookupMap[position.getRow()][position.getColumn()] == -1) { - return null; - } - return interactables.get(lookupMap[position.getRow()][position.getColumn()]); - } - - /** - * Starting from a particular {@code Interactable} and going up, which is the next interactable? - * @param interactable What {@code Interactable} to start searching from - * @return The next {@code Interactable} above the one specified or {@code null} if there are no more - * {@code Interactable}:s above it - */ - public synchronized Interactable findNextUp(Interactable interactable) { - return findNextUpOrDown(interactable, false); - } - - /** - * Starting from a particular {@code Interactable} and going down, which is the next interactable? - * @param interactable What {@code Interactable} to start searching from - * @return The next {@code Interactable} below the one specified or {@code null} if there are no more - * {@code Interactable}:s below it - */ - public synchronized Interactable findNextDown(Interactable interactable) { - return findNextUpOrDown(interactable, true); - } - - //Avoid code duplication in above two methods - private Interactable findNextUpOrDown(Interactable interactable, boolean isDown) { - int directionTerm = isDown ? 1 : -1; - TerminalPosition startPosition = interactable.getCursorLocation(); - if (startPosition == null) { - // If the currently active interactable component is not showing the cursor, use the top-left position - // instead if we're going up, or the bottom-left position if we're going down - if(isDown) { - startPosition = new TerminalPosition(0, interactable.getSize().getRows() - 1); - } - else { - startPosition = TerminalPosition.TOP_LEFT_CORNER; - } - } - else { - //Adjust position so that it's at the bottom of the component if we're going down or at the top of the - //component if we're going right. Otherwise the lookup might product odd results in certain cases. - if(isDown) { - startPosition = startPosition.withRow(interactable.getSize().getRows() - 1); - } - else { - startPosition = startPosition.withRow(0); - } - } - startPosition = interactable.toBasePane(startPosition); - if(startPosition == null) { - // The structure has changed, our interactable is no longer inside the base pane! - return null; - } - Set disqualified = getDisqualifiedInteractables(startPosition, true); - TerminalSize size = getSize(); - int maxShiftLeft = interactable.toBasePane(TerminalPosition.TOP_LEFT_CORNER).getColumn(); - maxShiftLeft = Math.max(maxShiftLeft, 0); - int maxShiftRight = interactable.toBasePane(new TerminalPosition(interactable.getSize().getColumns() - 1, 0)).getColumn(); - maxShiftRight = Math.min(maxShiftRight, size.getColumns() - 1); - int maxShift = Math.max(startPosition.getColumn() - maxShiftLeft, maxShiftRight - startPosition.getRow()); - for (int searchRow = startPosition.getRow() + directionTerm; - searchRow >= 0 && searchRow < size.getRows(); - searchRow += directionTerm) { - - for (int xShift = 0; xShift <= maxShift; xShift++) { - for (int modifier : new int[]{1, -1}) { - if (xShift == 0 && modifier == -1) { - break; - } - int searchColumn = startPosition.getColumn() + (xShift * modifier); - if (searchColumn < maxShiftLeft || searchColumn > maxShiftRight) { - continue; - } - - int index = lookupMap[searchRow][searchColumn]; - if (index != -1 && !disqualified.contains(interactables.get(index))) { - return interactables.get(index); - } - } - } - } - return null; - } - - /** - * Starting from a particular {@code Interactable} and going left, which is the next interactable? - * @param interactable What {@code Interactable} to start searching from - * @return The next {@code Interactable} left of the one specified or {@code null} if there are no more - * {@code Interactable}:s left of it - */ - public synchronized Interactable findNextLeft(Interactable interactable) { - return findNextLeftOrRight(interactable, false); - } - - /** - * Starting from a particular {@code Interactable} and going right, which is the next interactable? - * @param interactable What {@code Interactable} to start searching from - * @return The next {@code Interactable} right of the one specified or {@code null} if there are no more - * {@code Interactable}:s right of it - */ - public synchronized Interactable findNextRight(Interactable interactable) { - return findNextLeftOrRight(interactable, true); - } - - //Avoid code duplication in above two methods - private Interactable findNextLeftOrRight(Interactable interactable, boolean isRight) { - int directionTerm = isRight ? 1 : -1; - TerminalPosition startPosition = interactable.getCursorLocation(); - if(startPosition == null) { - // If the currently active interactable component is not showing the cursor, use the top-left position - // instead if we're going left, or the top-right position if we're going right - if(isRight) { - startPosition = new TerminalPosition(interactable.getSize().getColumns() - 1, 0); - } - else { - startPosition = TerminalPosition.TOP_LEFT_CORNER; - } - } - else { - //Adjust position so that it's on the left-most side if we're going left or right-most side if we're going - //right. Otherwise the lookup might product odd results in certain cases - if(isRight) { - startPosition = startPosition.withColumn(interactable.getSize().getColumns() - 1); - } - else { - startPosition = startPosition.withColumn(0); - } - } - startPosition = interactable.toBasePane(startPosition); - if(startPosition == null) { - // The structure has changed, our interactable is no longer inside the base pane! - return null; - } - Set disqualified = getDisqualifiedInteractables(startPosition, false); - TerminalSize size = getSize(); - int maxShiftUp = interactable.toBasePane(TerminalPosition.TOP_LEFT_CORNER).getRow(); - maxShiftUp = Math.max(maxShiftUp, 0); - int maxShiftDown = interactable.toBasePane(new TerminalPosition(0, interactable.getSize().getRows() - 1)).getRow(); - maxShiftDown = Math.min(maxShiftDown, size.getRows() - 1); - int maxShift = Math.max(startPosition.getRow() - maxShiftUp, maxShiftDown - startPosition.getRow()); - for(int searchColumn = startPosition.getColumn() + directionTerm; - searchColumn >= 0 && searchColumn < size.getColumns(); - searchColumn += directionTerm) { - - for(int yShift = 0; yShift <= maxShift; yShift++) { - for(int modifier: new int[] { 1, -1 }) { - if(yShift == 0 && modifier == -1) { - break; - } - int searchRow = startPosition.getRow() + (yShift * modifier); - if(searchRow < maxShiftUp || searchRow > maxShiftDown) { - continue; - } - int index = lookupMap[searchRow][searchColumn]; - if (index != -1 && !disqualified.contains(interactables.get(index))) { - return interactables.get(index); - } - } - } - } - return null; - } - - private Set getDisqualifiedInteractables(TerminalPosition startPosition, boolean scanHorizontally) { - Set disqualified = new HashSet(); - if (lookupMap.length == 0) { return disqualified; } // safeguard - - TerminalSize size = getSize(); - - //Adjust start position if necessary - if(startPosition.getRow() < 0) { - startPosition = startPosition.withRow(0); - } - else if(startPosition.getRow() >= lookupMap.length) { - startPosition = startPosition.withRow(lookupMap.length - 1); - } - if(startPosition.getColumn() < 0) { - startPosition = startPosition.withColumn(0); - } - else if(startPosition.getColumn() >= lookupMap[startPosition.getRow()].length) { - startPosition = startPosition.withColumn(lookupMap[startPosition.getRow()].length - 1); - } - - if(scanHorizontally) { - for(int column = 0; column < size.getColumns(); column++) { - int index = lookupMap[startPosition.getRow()][column]; - if(index != -1) { - disqualified.add(interactables.get(index)); - } - } - } - else { - for(int row = 0; row < size.getRows(); row++) { - int index = lookupMap[row][startPosition.getColumn()]; - if(index != -1) { - disqualified.add(interactables.get(index)); - } - } - } - return disqualified; - } - - void debug() { - for(int[] row: lookupMap) { - for(int value: row) { - if(value >= 0) { - System.out.print(" "); - } - System.out.print(value); - } - System.out.println(); - } - System.out.println(); - } -}