001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.hbtop.terminal.impl; 019 020import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.clearRemainingLine; 021import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.color; 022import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.cursor; 023import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.moveCursor; 024import static org.apache.hadoop.hbase.hbtop.terminal.impl.EscapeSequences.normal; 025 026import java.io.PrintWriter; 027import org.apache.hadoop.hbase.hbtop.terminal.Attributes; 028import org.apache.hadoop.hbase.hbtop.terminal.CursorPosition; 029import org.apache.yetus.audience.InterfaceAudience; 030 031 032/** 033 * Represents a buffer of the terminal screen for double-buffering. 034 */ 035@InterfaceAudience.Private 036public class ScreenBuffer { 037 private int columns; 038 private int rows; 039 040 private Cell[][] buffer; 041 private Cell[][] physical; 042 043 private boolean cursorVisible; 044 private int cursorColumn; 045 private int cursorRow; 046 047 public void reallocate(int columns, int rows) { 048 buffer = new Cell[columns][rows]; 049 physical = new Cell[columns][rows]; 050 051 for (int row = 0; row < rows; row++) { 052 for (int column = 0; column < columns; column++) { 053 buffer[column][row] = new Cell(); 054 055 physical[column][row] = new Cell(); 056 physical[column][row].unset(); 057 } 058 } 059 060 this.columns = columns; 061 this.rows = rows; 062 } 063 064 public void clear() { 065 for (int row = 0; row < rows; row++) { 066 for (int col = 0; col < columns; col++) { 067 buffer[col][row].reset(); 068 } 069 } 070 } 071 072 public void flush(PrintWriter output) { 073 StringBuilder sb = new StringBuilder(); 074 075 sb.append(normal()); 076 Attributes attributes = new Attributes(); 077 for (int row = 0; row < rows; row++) { 078 flushRow(row, sb, attributes); 079 } 080 081 if (cursorVisible && cursorRow >= 0 && cursorColumn >= 0 && cursorRow < rows && 082 cursorColumn < columns) { 083 sb.append(cursor(true)); 084 sb.append(moveCursor(cursorColumn, cursorRow)); 085 } else { 086 sb.append(cursor(false)); 087 } 088 089 output.write(sb.toString()); 090 output.flush(); 091 } 092 093 private void flushRow(int row, StringBuilder sb, Attributes lastAttributes) { 094 int lastColumn = -1; 095 for (int column = 0; column < columns; column++) { 096 Cell cell = buffer[column][row]; 097 Cell pCell = physical[column][row]; 098 099 if (!cell.equals(pCell)) { 100 if (lastColumn != column - 1 || lastColumn == -1) { 101 sb.append(moveCursor(column, row)); 102 } 103 104 if (cell.isEndOfLine()) { 105 for (int i = column; i < columns; i++) { 106 physical[i][row].set(buffer[i][row]); 107 } 108 109 sb.append(clearRemainingLine()); 110 lastAttributes.reset(); 111 return; 112 } 113 114 if (!cell.getAttributes().equals(lastAttributes)) { 115 sb.append(color(cell.getForegroundColor(), cell.getBackgroundColor(), cell.isBold(), 116 cell.isReverse(), cell.isBlink(), cell.isUnderline())); 117 } 118 119 sb.append(cell.getChar()); 120 121 lastColumn = column; 122 lastAttributes.set(cell.getAttributes()); 123 124 physical[column][row].set(cell); 125 } 126 } 127 } 128 129 public CursorPosition getCursorPosition() { 130 return new CursorPosition(cursorColumn, cursorRow); 131 } 132 133 public void setCursorPosition(int column, int row) { 134 cursorVisible = true; 135 cursorColumn = column; 136 cursorRow = row; 137 } 138 139 public void hideCursor() { 140 cursorVisible = false; 141 } 142 143 public void putString(int column, int row, String string, Attributes attributes) { 144 int i = column; 145 for (int j = 0; j < string.length(); j++) { 146 char ch = string.charAt(j); 147 putChar(i, row, ch, attributes); 148 i += 1; 149 if (i == columns) { 150 break; 151 } 152 } 153 } 154 155 public void putChar(int column, int row, char ch, Attributes attributes) { 156 if (column >= 0 && column < columns && row >= 0 && row < rows) { 157 buffer[column][row].setAttributes(attributes); 158 buffer[column][row].setChar(ch); 159 } 160 } 161 162 public void endOfLine(int column, int row) { 163 if (column >= 0 && column < columns && row >= 0 && row < rows) { 164 buffer[column][row].endOfLine(); 165 for (int i = column + 1; i < columns; i++) { 166 buffer[i][row].reset(); 167 } 168 } 169 } 170}