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 * Represents a buffer of the terminal screen for double-buffering. 033 */ 034@InterfaceAudience.Private 035public class ScreenBuffer { 036 private int columns; 037 private int rows; 038 039 private Cell[][] buffer; 040 private Cell[][] physical; 041 042 private boolean cursorVisible; 043 private int cursorColumn; 044 private int cursorRow; 045 046 public void reallocate(int columns, int rows) { 047 buffer = new Cell[columns][rows]; 048 physical = new Cell[columns][rows]; 049 050 for (int row = 0; row < rows; row++) { 051 for (int column = 0; column < columns; column++) { 052 buffer[column][row] = new Cell(); 053 054 physical[column][row] = new Cell(); 055 physical[column][row].unset(); 056 } 057 } 058 059 this.columns = columns; 060 this.rows = rows; 061 } 062 063 public void clear() { 064 for (int row = 0; row < rows; row++) { 065 for (int col = 0; col < columns; col++) { 066 buffer[col][row].reset(); 067 } 068 } 069 } 070 071 public void flush(PrintWriter output) { 072 StringBuilder sb = new StringBuilder(); 073 074 sb.append(normal()); 075 Attributes attributes = new Attributes(); 076 for (int row = 0; row < rows; row++) { 077 flushRow(row, sb, attributes); 078 } 079 080 if ( 081 cursorVisible && cursorRow >= 0 && cursorColumn >= 0 && cursorRow < rows 082 && cursorColumn < columns 083 ) { 084 sb.append(cursor(true)); 085 sb.append(moveCursor(cursorColumn, cursorRow)); 086 } else { 087 sb.append(cursor(false)); 088 } 089 090 output.write(sb.toString()); 091 output.flush(); 092 } 093 094 private void flushRow(int row, StringBuilder sb, Attributes lastAttributes) { 095 int lastColumn = -1; 096 for (int column = 0; column < columns; column++) { 097 Cell cell = buffer[column][row]; 098 Cell pCell = physical[column][row]; 099 100 if (!cell.equals(pCell)) { 101 if (lastColumn != column - 1 || lastColumn == -1) { 102 sb.append(moveCursor(column, row)); 103 } 104 105 if (cell.isEndOfLine()) { 106 for (int i = column; i < columns; i++) { 107 physical[i][row].set(buffer[i][row]); 108 } 109 110 sb.append(clearRemainingLine()); 111 lastAttributes.reset(); 112 return; 113 } 114 115 if (!cell.getAttributes().equals(lastAttributes)) { 116 sb.append(color(cell.getForegroundColor(), cell.getBackgroundColor(), cell.isBold(), 117 cell.isReverse(), cell.isBlink(), cell.isUnderline())); 118 } 119 120 sb.append(cell.getChar()); 121 122 lastColumn = column; 123 lastAttributes.set(cell.getAttributes()); 124 125 physical[column][row].set(cell); 126 } 127 } 128 } 129 130 public CursorPosition getCursorPosition() { 131 return new CursorPosition(cursorColumn, cursorRow); 132 } 133 134 public void setCursorPosition(int column, int row) { 135 cursorVisible = true; 136 cursorColumn = column; 137 cursorRow = row; 138 } 139 140 public void hideCursor() { 141 cursorVisible = false; 142 } 143 144 public void putString(int column, int row, String string, Attributes attributes) { 145 int i = column; 146 for (int j = 0; j < string.length(); j++) { 147 char ch = string.charAt(j); 148 putChar(i, row, ch, attributes); 149 i += 1; 150 if (i == columns) { 151 break; 152 } 153 } 154 } 155 156 public void putChar(int column, int row, char ch, Attributes attributes) { 157 if (column >= 0 && column < columns && row >= 0 && row < rows) { 158 buffer[column][row].setAttributes(attributes); 159 buffer[column][row].setChar(ch); 160 } 161 } 162 163 public void endOfLine(int column, int row) { 164 if (column >= 0 && column < columns && row >= 0 && row < rows) { 165 buffer[column][row].endOfLine(); 166 for (int i = column + 1; i < columns; i++) { 167 buffer[i][row].reset(); 168 } 169 } 170 } 171}